<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Android个人学习笔记 | Forgo7ten'blog</title><meta name="keywords" content="Android"><meta name="author" content="Forgo7ten"><meta name="copyright" content="Forgo7ten"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="Android ¶  [TOC] Android基础、项目目录结构 ¶  项目结构 ¶  Project ¶    .gradle和.idea：这两个目录下放置的都是Android Studio自动生成的一些文件，我们无须关心，也不要去手动编辑。   app：项目中的代码、资源等内容几乎都是放置在这个目录下的，开发工作也基本都是在这个目录下进行的。   build：这个目录你也不需要过多关心，它主">
<meta property="og:type" content="article">
<meta property="og:title" content="Android个人学习笔记">
<meta property="og:url" content="https://forgo7ten.github.io/Development/android/Android_Development_Notes/index.html">
<meta property="og:site_name" content="Forgo7ten&#39;blog">
<meta property="og:description" content="Android ¶  [TOC] Android基础、项目目录结构 ¶  项目结构 ¶  Project ¶    .gradle和.idea：这两个目录下放置的都是Android Studio自动生成的一些文件，我们无须关心，也不要去手动编辑。   app：项目中的代码、资源等内容几乎都是放置在这个目录下的，开发工作也基本都是在这个目录下进行的。   build：这个目录你也不需要过多关心，它主">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://forgo7ten.gitee.io/store/imgs/10.jpg">
<meta property="article:published_time" content="2021-03-07T16:00:00.000Z">
<meta property="article:modified_time" content="2021-03-07T16:00:00.000Z">
<meta property="article:author" content="Forgo7ten">
<meta property="article:tag" content="Android">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://forgo7ten.gitee.io/store/imgs/10.jpg"><link rel="shortcut icon" href="/images/favicon.jpg"><link rel="canonical" href="https://forgo7ten.github.io/Development/android/Android_Development_Notes/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//hm.baidu.com"/><link rel="preconnect" href="//www.clarity.ms"/><link rel="preconnect" href="//fonts.googleapis.com" crossorigin=""/><link rel="preconnect" href="//busuanzi.ibruce.info"/><meta name="google-site-verification" content="8L0ZjthONyq6-m7FniRTH8A7Bh0x-KOPZbKOcNimnYA"/><meta name="baidu-site-verification" content="code-gjVsyPt7yr"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css" media="print" onload="this.media='all'"><script>var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?b076845d73a4f28b3c7401b2a0a8a9db";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script><script>(function(c,l,a,r,i,t,y){
    c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
    t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
    y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "9zbibmmffi");</script><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Titillium+Web&amp;display=swap" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容：${query}"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"簡"},
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":300},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: true,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#121212","position":"bottom-left"},
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: true
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'Android个人学习笔记',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2021-03-08 00:00:00'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="Forgo7ten'blog" type="application/atom+xml">
</head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/images/avatar.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data is-center"><div class="data-item"><a href="/archives/"><div class="headline">文章</div><div class="length-num">20</div></a></div><div class="data-item"><a href="/tags/"><div class="headline">标签</div><div class="length-num">8</div></a></div><div class="data-item"><a href="/categories/"><div class="headline">分类</div><div class="length-num">6</div></a></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-compass"></i><span> 目录</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></li><li><a class="site-page child" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/atom.xml"><i class="fa-fw fa fa-rss"></i><span> RSS订阅</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fas fa-comment-dots"></i><span> 留言板</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('http://forgo7ten.gitee.io/store/imgs/10.jpg')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">Forgo7ten'blog</a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-compass"></i><span> 目录</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></li><li><a class="site-page child" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/atom.xml"><i class="fa-fw fa fa-rss"></i><span> RSS订阅</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fas fa-comment-dots"></i><span> 留言板</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">Android个人学习笔记</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-03-07T16:00:00.000Z" title="发表于 2021-03-08 00:00:00">2021-03-08</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2021-03-07T16:00:00.000Z" title="更新于 2021-03-08 00:00:00">2021-03-08</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E5%BC%80%E5%8F%91/">开发</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">28.7k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>119分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="Android个人学习笔记"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="Android">Android<a class="header-anchor" href="#Android"> ¶ </a></h1>
<p>[TOC]</p>
<h2 id="Android基础、项目目录结构">Android基础、项目目录结构<a class="header-anchor" href="#Android基础、项目目录结构"> ¶ </a></h2>
<h3 id="项目结构">项目结构<a class="header-anchor" href="#项目结构"> ¶ </a></h3>
<h4 id="Project">Project<a class="header-anchor" href="#Project"> ¶ </a></h4>
<ol>
<li>
<p>.gradle和.idea：这两个目录下放置的都是Android Studio自动生成的一些文件，我们无须关心，也不要去手动编辑。</p>
</li>
<li>
<p>app：项目中的代码、资源等内容几乎都是放置在这个目录下的，开发工作也基本都是在这个目录下进行的。</p>
</li>
<li>
<p>build：这个目录你也不需要过多关心，它主要包含了一些在编译时自动生成的文件。</p>
</li>
<li>
<p>gradle：这个目录下包含了gradle wrapper的配置文件，使用gradle wrapper的方式不需要提前将gradle下载好，而是会自动根据本地的缓存情况决定是否需要联网下载gradle。Android Studio默认没有启用gradlewrapper的方式，如果需要打开，可以点击Android Studio导航栏→File→Settings→Build, Execution,Deployment→Gradle，进行配置更改。</p>
</li>
<li>
<p>.gitignore：这个文件是用来将指定的目录或文件排除在版本控制之外的</p>
</li>
<li>
<p>build.gradle：这是项目全局的gradle构建脚本，通常这个文件中的内容是不需要修改的。</p>
</li>
<li>
<p>gradle.properties：这个文件是全局的gradle配置文件，在这里配置的属性将会影响到项目中所有的gradle编译脚本。</p>
</li>
<li>
<p>gradlew和gradlew.bat：这两个文件是用来在命令行界面中执行gradle命令的，其中gradlew是在Linux或Mac系统中使用的，gradlew.bat是在Windows系统中使用的。</p>
</li>
<li>
<p>HelloWorld.iml：<br>
iml文件是所有IntelliJ IDEA项目都会自动生成的一个文件（Android Studio是基于IntelliJ IDEA开发的），用于标识这是一个IntelliJ IDEA项目，我们不需要修改这个文件中的任何内容。</p>
</li>
<li>
<p>local.properties：这个文件用于指定本机中的Android SDK路径，通常内容都是自动生成的，我们并不需要修改。除非你本机中的Android SDK位置发生了变化，那么就将这个文件中的路径改成新的位置即可。</p>
</li>
<li>
<p>settings.gradle：<br>
这个文件用于指定项目中所有引入的模块。由于HelloWorld项目中就只有一个app模块，因此该文件中也就只引入了app这一个模块。通常情况下模块的引入都是自动完成的，需要我们手动去修改这个文件的场景可能比较少。</p>
</li>
</ol>
<h4 id="app目录">app目录<a class="header-anchor" href="#app目录"> ¶ </a></h4>
<ol>
<li>
<p>build：这个目录和外层的build目录类似，主要也是包含了一些在编译时自动生成的文件，不过它里面的内容会更多更杂，我们不需要过多关心。</p>
</li>
<li>
<p>libs：如果你的项目中使用到了第三方jar包，就需要把这些jar包都放在libs目录下，放在这个目录下的jar包都会被自动添加到构建路径里去。</p>
</li>
<li>
<p>androidTest：此处是用来编写Android Test测试用例的，可以对项目进行一些自动化测试。</p>
</li>
<li>
<p>java：毫无疑问，java目录是放置我们所有Java代码的地方，展开该目录，你将看到我们刚才创建的HelloWorldActivity文件就在里面。</p>
</li>
<li>
<p>res：这个目录下的内容就有点多了。简单点说，就是你在项目中使用到的所有图片、布局、字符串等资源都要存放在这个目录下。当然这个目录下还有很多子目录，图片放在<br>
drawable目录下，布局放在layout目录下，字符串放在values目录下，所以你不用担心<br>
会把整个res目录弄得乱糟糟的。</p>
</li>
<li>
<p>AndroidManifest.xml：这是你整个Android项目的配置文件，你在程序中定义的所有四大组件都需要在这个文件里注册，另外还可以在这个文件中给应用程序添加权限声明。</p>
</li>
<li>
<p>test：此处是用来编写Unit Test测试用例的，是对项目进行自动化测试的另一种方式。</p>
</li>
<li>
<p>.gitignore：这个文件用于将app模块内的指定的目录或文件排除在版本控制之外，作用和外层的.gitignore文件类似。</p>
</li>
<li>
<p>app.iml：IntelliJ IDEA项目自动生成的文件，我们不需要关心或修改这个文件中的内容。</p>
</li>
<li>
<p>build.gradle：这是app模块的gradle构建脚本，这个文件中会指定很多项目构建相关的配置。</p>
</li>
<li>
<p><a target="_blank" rel="noopener" href="http://proguard-rules.pro">proguard-rules.pro</a>：这个文件用于指定项目代码的混淆规则，当代码开发完成后打成安装包文件，如果不希望代码被别人破解，通常会将代码进行混淆，从而让破解者难以阅读。</p>
</li>
</ol>
<h4 id="build-gradle文件">build.gradle文件<a class="header-anchor" href="#build-gradle文件"> ¶ </a></h4>
<p>HelloWorld项目中有两个build.gradle文件，一个是在最外层目录下的，一个是在app目录下的。</p>
<h6 id="最外层目录build-gradle">最外层目录build.gradle<a class="header-anchor" href="#最外层目录build-gradle"> ¶ </a></h6>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">buildscript &#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        jcenter()</span><br><span class="line">    &#125;</span><br><span class="line">    dependencies &#123;</span><br><span class="line">        classpath <span class="string">&#x27;com.android.tools.build:gradle:2.2.0&#x27;</span></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">allprojects &#123;</span><br><span class="line">    repositories &#123;</span><br><span class="line">        jcenter()</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>两处<code>repositories</code> 的闭包中都声明了<code>jcenter()</code></p>
<p>jcenter是一个代码托管仓库，很多Android开源项目都会选择将代码托管到jcenter上，声明了这行配置之后，我们就可以在项目中轻松引用任何jcenter上的开源项目。</p>
<p>dependencies 闭包中使用classpath声明了一个Gradle插件来构建Android项目，声明<br>
<code>com.android.tools.build:gradle:2.2.0</code> 这个插件。其中，最后面的部分是插件的版本号，为2.2.0</p>
<h6 id="app内部build-gradle">app内部build.gradle<a class="header-anchor" href="#app内部build-gradle"> ¶ </a></h6>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">apply <span class="attr">plugin:</span> <span class="string">&#x27;com.android.application&#x27;</span>     <span class="comment">// 应用插件</span></span><br><span class="line"></span><br><span class="line">android &#123;</span><br><span class="line">    compileSdkVersion <span class="number">24</span>        <span class="comment">// 指定项目的编译版本</span></span><br><span class="line">    buildToolsVersion <span class="string">&quot;24.0.2&quot;</span>  <span class="comment">// 指定项目构建工具的版本</span></span><br><span class="line">    defaultConfig &#123;</span><br><span class="line">        applicationId <span class="string">&quot;com.example.helloworld&quot;</span>  <span class="comment">// 指定项目的包名</span></span><br><span class="line">        minSdkVersion <span class="number">15</span>        <span class="comment">// 指定项目最低兼容的Android系统版本</span></span><br><span class="line">        targetSdkVersion <span class="number">24</span>     <span class="comment">// 指定的值表示你在该目标版本上已经做过了充分的测试，会启用该版本的新特性(目标版本)</span></span><br><span class="line">        versionCode <span class="number">1</span>           <span class="comment">// 指定项目的版本号</span></span><br><span class="line">        versionName <span class="string">&quot;1.0&quot;</span>       <span class="comment">// 指定项目的版本名</span></span><br><span class="line">    &#125;</span><br><span class="line">    buildTypes &#123;</span><br><span class="line">        release &#123;</span><br><span class="line">            minifyEnabled <span class="literal">false</span> <span class="comment">// 指定是否对项目的代码进行混淆，true 表示混淆，false 表示不混淆</span></span><br><span class="line">            proguardFiles getDefaultProguardFile(<span class="string">&#x27;proguard-android-optimize.txt&#x27;</span>), <span class="string">&#x27;proguard-rules.pro&#x27;</span></span><br><span class="line">            <span class="comment">// proguardFiles 用于指定混淆时使用的规则文件，这里指定了两个文件</span></span><br><span class="line">            <span class="comment">// 第一个proguard-android.txt 是在Android SDK目录下的，里面是所有项目通用的混淆规则；</span></span><br><span class="line">            <span class="comment">// 第二个proguard-rules.pro 是在当前项目的根目录下的，里面可以编写当前项目特有的混淆规则</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">dependencies &#123;	<span class="comment">// 指定当前项目所有的依赖关系</span></span><br><span class="line">    compile fileTree(<span class="attr">dir:</span> <span class="string">&#x27;libs&#x27;</span>, <span class="attr">include:</span> [<span class="string">&#x27;*.jar&#x27;</span>])</span><br><span class="line">    compile <span class="string">&#x27;com.android.support:appcompat-v7:24.2.1&#x27;</span></span><br><span class="line"></span><br><span class="line">    testCompile <span class="string">&#x27;junit:junit:4.12&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>第一行<code>apply plugin</code>应用了一个插件，一般有两种值可选：<code>com.android.application </code>表示这是一个应用程序模块，<code>com.android.library</code> 表示这是一个库模块。应用程序模块和库模块的最大区别在于，一个是可以直接运行的，一个只能作为代码库依附于别的应用程序模块来运行</p>
</li>
<li>
<p><code>dependencies</code>依赖：</p>
<ul>
<li>
<p>通常Android Studio项目一共有3种依<br>
赖方式：本地依赖、库依赖和远程依赖。</p>
<ul>
<li>本地依赖可以对本地的Jar包或目录添加依赖关系</li>
<li>库依赖可以对项目中的库模块添加依赖关系</li>
<li>远程依赖则可以对jcenter库上的开源项目添加依赖关系。</li>
</ul>
</li>
<li>
<p>观察一下<code>dependencies</code>闭包中的配置，第一行的<code>compile fileTree</code> 就是一个本地依赖声明，它表示将<code>libs</code>目录下所有.jar后缀的文件都添加到项目的构建路径当中。</p>
</li>
<li>
<p>而第二行的compile则是远程依赖声明，<code>com.android.support:appcompat-v7:24.2.1</code>就是一个标准的远程依赖库格式，其中<code>com.android.support</code> 是域名部分，用于和其他公司的库做区分；<code>appcompat-v7</code> 是组名称，用于和同一个公司中不同的库做区分；<code>24.2.1</code>是版本号，用于和同一个库不同的版本做区分。</p>
<p>加上这句声明后，Gradle在构建项目时会首先检查一下本地是否已经有这个库的缓存，如果没有的话则会去自动联网下载，然后再添加到项目的构建路径当中。</p>
</li>
<li>
<p>库依赖声明这里没有用到，它的基本格式是<code>compile project 后面加上要依赖的库名称</code>，比如说有一个库模块的名字叫helper，那么添加这个库的依赖关系只需要加入<code>compile project(':helper')</code> 这句声明即可。</p>
</li>
<li>
<p>另外剩下的一句testCompile 是用于声明测试用例库的，这个我们暂时用不到，先忽略它就可以了</p>
</li>
</ul>
</li>
</ul>
<h4 id="res资源目录">res资源目录<a class="header-anchor" href="#res资源目录"> ¶ </a></h4>
<ul>
<li>所有以drawable开头的文件夹都是用来放图片的</li>
<li>所有以mipmap开头的文件夹都是用来放应用图标的</li>
<li>所有以values开头的文件夹都是用来放字符串、样式、颜色等配置的</li>
<li>layout文件夹是用来放布局文件的</li>
</ul>
<p>mipmap开头的文件夹，其实主要是为了让程序能够更好地兼容各种设备。drawable文件夹也是相同的道理，虽然Android Studio没有帮我们自动生成，但是我们应该自己创建drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等文件夹</p>
<h5 id="string-xml字符串资源">string.xml字符串资源<a class="header-anchor" href="#string-xml字符串资源"> ¶ </a></h5>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">string</span> <span class="attr">name</span>=<span class="string">&quot;app_name&quot;</span>&gt;</span>HelloWorld<span class="tag">&lt;/<span class="name">string</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>当需要引用时</p>
<ul>
<li>在代码中通过<code>R.string.app_name</code> 可以获得该字符串的引用。</li>
<li>在XML中通过<code>@string/app_name</code> 可以获得该字符串的引用。</li>
</ul>
<h3 id="日志工具使用">日志工具使用<a class="header-anchor" href="#日志工具使用"> ¶ </a></h3>
<h4 id="使用Android的日志工具Log">使用Android的日志工具Log<a class="header-anchor" href="#使用Android的日志工具Log"> ¶ </a></h4>
<p>Android中的日志工具类是Log（android.util.Log），这个类中提供了如下5个方法来供我们打印日志。</p>
<ul>
<li><code>Log.v()</code> 。用于打印那些最为琐碎的、意义最小的日志信息。对应级别<code>verbose</code>，是Android日志里面级别最低的一种。</li>
<li><code>Log.d()</code> 。用于打印一些调试信息，这些信息对你调试程序和分析问题应该是有帮助的。对应级别<code>debug</code>，比verbose高一级。</li>
<li><code>Log.i()</code> 。用于打印一些比较重要的数据，这些数据应该是你非常想看到的、可以帮你分析用户行为数据。对应级别<code>info</code>，比debug高一级。</li>
<li><code>Log.w()</code> 。用于打印一些警告信息，提示程序在这个地方可能会有潜在的风险，最好去修复一下这些出现警告的地方。对应级别<code>warn</code>，比info高一级。</li>
<li><code>Log.e()</code> 。用于打印程序中的错误信息，比如程序进入到了catch语句当中。当有错误信息打印出来的时候，一般都代表你的程序出现严重问题了，必须尽快修复。对应级别<code>error</code>，比warn高一级</li>
</ul>
<h2 id="Android-UI控件">Android UI控件<a class="header-anchor" href="#Android-UI控件"> ¶ </a></h2>
<table>
<thead>
<tr>
<th>控件</th>
<th style="text-align:center">属性</th>
<th style="text-align:center">作用</th>
<th style="text-align:center">值</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td style="text-align:center"><code>android:layout_width</code></td>
<td style="text-align:center">设置宽</td>
<td style="text-align:center">match_parent <br>fill_parent <br>wrap_content</td>
</tr>
<tr>
<td></td>
<td style="text-align:center"><code>android:layout_height</code></td>
<td style="text-align:center">设置高</td>
<td style="text-align:center">xx dp</td>
</tr>
<tr>
<td></td>
<td style="text-align:center"><code>android:gravity</code></td>
<td style="text-align:center">内容对齐方式</td>
<td style="text-align:center">top 、bottom 、left 、right、center</td>
</tr>
<tr>
<td></td>
<td style="text-align:center"><code>android:text</code></td>
<td style="text-align:center">文字内容</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td></td>
<td style="text-align:center"><code>android:textSize</code></td>
<td style="text-align:center">文字大小</td>
<td style="text-align:center">xx sp</td>
</tr>
<tr>
<td></td>
<td style="text-align:center"><code>android:textColor</code></td>
<td style="text-align:center">文字颜色</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td></td>
<td style="text-align:center"><code>android:textAllCaps</code></td>
<td style="text-align:center">文字全部大写</td>
<td style="text-align:center"><code>true</code>/<code>false</code></td>
</tr>
<tr>
<td>EditText</td>
<td style="text-align:center"><code>android:maxLines</code></td>
<td style="text-align:center">指定最大行数</td>
<td style="text-align:center">[number]</td>
</tr>
<tr>
<td>ImageView</td>
<td style="text-align:center"><code>android:src</code></td>
<td style="text-align:center">设置图片路径</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td></td>
<td style="text-align:center"><code>android:visibility</code></td>
<td style="text-align:center">设置控件可见属性</td>
<td style="text-align:center">visible 、invisible 和gone</td>
</tr>
<tr>
<td>ProgressBar</td>
<td style="text-align:center"><code>style=&quot;?android:attr/progressBarStyleHorizontal&quot;</code></td>
<td style="text-align:center">水平进度条</td>
<td style="text-align:center"></td>
</tr>
<tr>
<td>ProgressBar</td>
<td style="text-align:center"><code>android:max</code></td>
<td style="text-align:center">进度条最大值</td>
<td style="text-align:center">100</td>
</tr>
<tr>
<td></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
<tr>
<td></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
<td style="text-align:center"></td>
</tr>
</tbody>
</table>
<h3 id="AlertDialog">AlertDialog<a class="header-anchor" href="#AlertDialog"> ¶ </a></h3>
<p>对话框</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用builder生成一个dialog</span></span><br><span class="line">AlertDialog.Builder dialog = <span class="keyword">new</span> AlertDialog.Builder (MainActivity.<span class="keyword">this</span>);</span><br><span class="line"><span class="comment">// 设置标题</span></span><br><span class="line">dialog.setTitle(<span class="string">&quot;This is Dialog&quot;</span>);</span><br><span class="line"><span class="comment">// 设置内容</span></span><br><span class="line">dialog.setMessage(<span class="string">&quot;Something important.&quot;</span>);</span><br><span class="line"><span class="comment">// 可否用Back键关闭对话框</span></span><br><span class="line">dialog.setCancelable(<span class="keyword">false</span>);</span><br><span class="line"><span class="comment">// 设置确定按钮</span></span><br><span class="line">dialog.setPositiveButton(<span class="string">&quot;OK&quot;</span>, <span class="keyword">new</span> DialogInterface.</span><br><span class="line">    OnClickListener() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(DialogInterface dialog, <span class="keyword">int</span> which)</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 设置取消按钮</span></span><br><span class="line">dialog.setNegativeButton(<span class="string">&quot;Cancel&quot;</span>, <span class="keyword">new</span> DialogInterface.</span><br><span class="line">    OnClickListener() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(DialogInterface dialog, <span class="keyword">int</span> which)</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 创建dialog</span></span><br><span class="line">dialog.create();</span><br><span class="line"><span class="comment">// 展示dialog</span></span><br><span class="line">dialog.show();</span><br></pre></td></tr></table></figure>
<p>如果需要自定义对话框视图</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_add_friend, <span class="keyword">null</span>);</span><br><span class="line">AlertDialog.Builder builder = <span class="keyword">new</span> AlertDialog.Builder(mContext);</span><br><span class="line">builder.setView(view);</span><br><span class="line">submitBtn = view.findViewById(R.id.btn_submit);</span><br></pre></td></tr></table></figure>
<h3 id="ProgressDialog">ProgressDialog<a class="header-anchor" href="#ProgressDialog"> ¶ </a></h3>
<p>进度条对话框</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ProgressDialog progressDialog = <span class="keyword">new</span> ProgressDialog(MainActivity.<span class="keyword">this</span>);</span><br><span class="line">progressDialog.setTitle(<span class="string">&quot;This is ProgressDialog&quot;</span>);</span><br><span class="line">progressDialog.setMessage(<span class="string">&quot;Loading...&quot;</span>);</span><br><span class="line">progressDialog.setCancelable(<span class="keyword">true</span>);</span><br><span class="line">progressDialog.show();</span><br></pre></td></tr></table></figure>
<h3 id="菜单Menu">菜单Menu<a class="header-anchor" href="#菜单Menu"> ¶ </a></h3>
<h4 id="1-新建菜单Menu资源文件">1. 新建菜单Menu资源文件<a class="header-anchor" href="#1-新建菜单Menu资源文件"> ¶ </a></h4>
<p>在<code>res/menu/*.xml</code></p>
<p>menu.xml</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">menu</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">item</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/add_item&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:title</span>=<span class="string">&quot;Add&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">item</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/remove_item&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:title</span>=<span class="string">&quot;Remove&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">menu</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="2-Activity重写onCreateOptionsMenu-方法">2. Activity重写<code>onCreateOptionsMenu()</code>方法<a class="header-anchor" href="#2-Activity重写onCreateOptionsMenu-方法"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onCreateOptionsMenu</span><span class="params">(Menu menu)</span> </span>&#123;</span><br><span class="line">    getMenuInflater().inflate(R.menu.main, menu);</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>inflate([布局文件],Menu)</p>
<p>返回值为<code>true</code>表示允许将创建的菜单显示出来</p>
<h4 id="3-重写onOptionsItemSelected-方法">3. 重写<code>onOptionsItemSelected()</code>方法<a class="header-anchor" href="#3-重写onOptionsItemSelected-方法"> ¶ </a></h4>
<p>来注册菜单响应事件</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onOptionsItemSelected</span><span class="params">(MenuItem item)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (item.getItemId()) &#123;</span><br><span class="line">    <span class="keyword">case</span> R.id.add_item:</span><br><span class="line"></span><br><span class="line">        Toast.makeText(<span class="keyword">this</span>, <span class="string">&quot;You clicked Add&quot;</span>, Toast.LENGTH_SHORT).show();</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">case</span> R.id.remove_item:</span><br><span class="line">        Toast.makeText(<span class="keyword">this</span>, <span class="string">&quot;You clicked Remove&quot;</span>, Toast.LENGTH_SHORT).show();</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="WebView用法">WebView用法<a class="header-anchor" href="#WebView用法"> ¶ </a></h3>
<p>layout</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">LinearLayout</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span> &gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">WebView</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/web_view&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">LinearLayout</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>activity</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">    setContentView(R.layout.activity_main);</span><br><span class="line">    WebView webView = (WebView) findViewById(R.id.web_view);</span><br><span class="line">    <span class="comment">// 启用JS支持</span></span><br><span class="line">    webView.getSettings().setJavaScriptEnabled(<span class="keyword">true</span>);</span><br><span class="line">    <span class="comment">// 当需要从一个网页跳转到另一个网页时，我们希望目标网页仍然在当前WebView中显示，而不是打开系统浏览器</span></span><br><span class="line">    webView.setWebViewClient(<span class="keyword">new</span> WebViewClient());</span><br><span class="line">    <span class="comment">// 加载网页 也可以加载本地的html文件</span></span><br><span class="line">    webView.loadUrl(<span class="string">&quot;http://www.baidu.com&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>需声明网络权限</p>
<h3 id="ListView">ListView<a class="header-anchor" href="#ListView"> ¶ </a></h3>
<h4 id="1-编写子元素界面">1. 编写子元素界面<a class="header-anchor" href="#1-编写子元素界面"> ¶ </a></h4>
<h4 id="2-编写Adapter">2. 编写Adapter<a class="header-anchor" href="#2-编写Adapter"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FriendsAdapter</span> <span class="keyword">extends</span> <span class="title">BaseAdapter</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 界面的布局ID</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">int</span> itemLayoutId;</span><br><span class="line">    <span class="comment">// 数据</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> List&lt;String&gt; friendsName;</span><br><span class="line">    <span class="comment">// 环境上下文</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> Context mContext;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">FriendsAdapter</span><span class="params">(<span class="keyword">int</span> itemLayoutId, List&lt;String&gt; friendsName, Context mContext)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 界面的布局ID</span></span><br><span class="line">        <span class="keyword">this</span>.itemLayoutId = itemLayoutId;</span><br><span class="line">        <span class="comment">// 数据源</span></span><br><span class="line">        <span class="keyword">this</span>.friendsName = friendsName;</span><br><span class="line">        <span class="comment">// 环境上下文</span></span><br><span class="line">        <span class="keyword">this</span>.mContext = mContext;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getCount</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 获得数据的长度</span></span><br><span class="line">        <span class="keyword">if</span> (friendsName != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> friendsName.size();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">getItem</span><span class="params">(<span class="keyword">int</span> position)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 获得数据的某个元素</span></span><br><span class="line">        <span class="keyword">if</span> (friendsName != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> friendsName.get(position);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">long</span> <span class="title">getItemId</span><span class="params">(<span class="keyword">int</span> position)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 获得某个元素的id</span></span><br><span class="line">        <span class="keyword">return</span> position;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> View <span class="title">getView</span><span class="params">(<span class="keyword">int</span> position, View convertView, ViewGroup parent)</span> </span>&#123;</span><br><span class="line">        ViewHolder viewHolder;</span><br><span class="line">        <span class="comment">//需要加载子Item的布局，并获取布局中的控件元素，而且设置相应的数据源值</span></span><br><span class="line">        <span class="comment">//1. 获取子布局</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">null</span> == convertView) &#123;</span><br><span class="line">            <span class="comment">// 初始化布局</span></span><br><span class="line">            convertView = LayoutInflater.from(mContext).inflate(itemLayoutId, <span class="keyword">null</span>);</span><br><span class="line">            <span class="comment">//初始化ViewHolder对象，以方便保存子布局</span></span><br><span class="line">            viewHolder = <span class="keyword">new</span> ViewHolder();</span><br><span class="line">            <span class="comment">//给ViewHolder的属性赋值（初始化页面的控件）</span></span><br><span class="line">            viewHolder.friendNameTv = convertView.findViewById(R.id.friend_name);</span><br><span class="line">            <span class="comment">//保存子布局</span></span><br><span class="line">            convertView.setTag(viewHolder);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">//获取已经保存的子布局</span></span><br><span class="line">            viewHolder = (ViewHolder) convertView.getTag();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 给子布局中的控件设置相应的数据源值</span></span><br><span class="line">        <span class="comment">// 得到子Item的数据</span></span><br><span class="line">        String name = friendsName.get(position);</span><br><span class="line">        viewHolder.friendNameTv.setText(name);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> convertView;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ViewHolder</span> </span>&#123;</span><br><span class="line">        TextView friendNameTv;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h4 id="3-给listView对象设置adapter">3. 给listView对象设置adapter<a class="header-anchor" href="#3-给listView对象设置adapter"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">adapter = <span class="keyword">new</span> NewsListAdapter(R.layout.layout_item, newsList, getContext());</span><br><span class="line">list.setAdapter(adapter);</span><br></pre></td></tr></table></figure>
<h3 id="RecyclerView滚动控件">RecyclerView滚动控件<a class="header-anchor" href="#RecyclerView滚动控件"> ¶ </a></h3>
<h5 id="添加依赖">添加依赖<a class="header-anchor" href="#添加依赖"> ¶ </a></h5>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">dependencies</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">compile</span> <span class="keyword">fileTree</span>(dir: <span class="string">&#x27;libs&#x27;</span>, <span class="keyword">include</span>: [<span class="string">&#x27;*.jar&#x27;</span>])</span><br><span class="line">    <span class="keyword">compile</span> <span class="string">&#x27;com.android.support:appcompat-v7:24.2.1&#x27;</span></span><br><span class="line">    <span class="keyword">compile</span> <span class="string">&#x27;com.android.support:recyclerview-v7:24.2.1&#x27;</span></span><br><span class="line">    testCompile <span class="string">&#x27;junit:junit:4.12&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h5 id="Layout引用">Layout引用<a class="header-anchor" href="#Layout引用"> ¶ </a></h5>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">android.support.v7.widget.RecyclerView</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/recycler_view&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="Adapter自定义适配器">Adapter自定义适配器<a class="header-anchor" href="#Adapter自定义适配器"> ¶ </a></h5>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FruitAdapter</span> <span class="keyword">extends</span> <span class="title">RecyclerView</span>.<span class="title">Adapter</span>&lt;<span class="title">FruitAdapter</span>.<span class="title">ViewHolder</span>&gt; </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;Fruit&gt; mFruitList;</span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">ViewHolder</span> <span class="keyword">extends</span> <span class="title">RecyclerView</span>.<span class="title">ViewHolder</span> </span>&#123;</span><br><span class="line">        ImageView fruitImage;</span><br><span class="line">        TextView fruitName;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="title">ViewHolder</span><span class="params">(View view)</span> </span>&#123;</span><br><span class="line">            <span class="keyword">super</span>(view);</span><br><span class="line">            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);</span><br><span class="line">            fruitName = (TextView) view.findViewById(R.id.fruit_name);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">FruitAdapter</span><span class="params">(List&lt;Fruit&gt; fruitList)</span> </span>&#123;</span><br><span class="line">        mFruitList = fruitList;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> ViewHolder <span class="title">onCreateViewHolder</span><span class="params">(ViewGroup parent, <span class="keyword">int</span> viewType)</span> </span>&#123;</span><br><span class="line">        View view = LayoutInflater.from(parent.getContext())</span><br><span class="line">            .inflate(R.layout.fruit_item, parent, <span class="keyword">false</span>);</span><br><span class="line">        ViewHolder holder = <span class="keyword">new</span> ViewHolder(view);</span><br><span class="line">        <span class="keyword">return</span> holder;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onBindViewHolder</span><span class="params">(ViewHolder holder, <span class="keyword">int</span> position)</span> </span>&#123;</span><br><span class="line">        Fruit fruit = mFruitList.get(position);</span><br><span class="line">        holder.fruitImage.setImageResource(fruit.getImageId());</span><br><span class="line">        holder.fruitName.setText(fruit.getName());</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getItemCount</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> mFruitList.size();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>onCreateViewHolder() 方法是用于创建ViewHolder实例</p>
<p>onBindViewHolder() 方法是用于对RecyclerView子项的数据进行赋值</p>
<p>getItemCount() 用于告诉RecyclerView一共有多少子项</p>
<h5 id="调用生成">调用生成<a class="header-anchor" href="#调用生成"> ¶ </a></h5>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">    setContentView(R.layout.activity_main);</span><br><span class="line">    initFruits(); <span class="comment">// 初始化水果数据</span></span><br><span class="line">    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);</span><br><span class="line">    LinearLayoutManager layoutManager = <span class="keyword">new</span> LinearLayoutManager(<span class="keyword">this</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 设置水平排列</span></span><br><span class="line">    <span class="comment">// layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 设置瀑布流</span></span><br><span class="line">    <span class="comment">// StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);</span></span><br><span class="line">    </span><br><span class="line">    recyclerView.setLayoutManager(layoutManager);</span><br><span class="line">    FruitAdapter adapter = <span class="keyword">new</span> FruitAdapter(fruitList);</span><br><span class="line">    recyclerView.setAdapter(adapter);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h5 id="点击事件">点击事件<a class="header-anchor" href="#点击事件"> ¶ </a></h5>
<p>点击事件写到<code>onCreateViewHolder()</code>方法</p>
<h3 id="布局">布局<a class="header-anchor" href="#布局"> ¶ </a></h3>
<h4 id="LinearLayout线性布局">LinearLayout线性布局<a class="header-anchor" href="#LinearLayout线性布局"> ¶ </a></h4>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">LinearLayout</span></span></span><br><span class="line"><span class="tag">    // 指定排列方向 垂直/水平</span></span><br><span class="line"><span class="tag">    <span class="attr">android:orientation</span>=<span class="string">&quot;vertical/horizontal&quot;</span></span></span><br><span class="line"><span class="tag">    // 指定该控件在布局中的对齐方式</span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_gravity</span>=<span class="string">&quot;center...&quot;</span></span></span><br><span class="line"><span class="tag">    // 设置比例，设置后相应的宽/高需设置为<span class="attr">0dp</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_weight</span>=<span class="string">&quot;weight(num)&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">LinearLayout</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="RelativeLayout相对布局">RelativeLayout相对布局<a class="header-anchor" href="#RelativeLayout相对布局"> ¶ </a></h4>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Button</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:id</span>=<span class="string">&quot;@+id/button1&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    // 与父布局的左对齐</span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_alignParentLeft</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    // 与父布局的右对齐</span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_alignParentTop</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    // 在父布局的正中间</span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_centerInParent</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    // 在<span class="attr">button3</span>的上方</span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_above</span>=<span class="string">&quot;@id/button3&quot;</span></span></span><br><span class="line"><span class="tag">    // 在<span class="attr">button3</span>的左方</span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_toLeftOf</span>=<span class="string">&quot;@id/button3&quot;</span></span></span><br><span class="line"><span class="tag">    // 该控件的左边缘与<span class="attr">button3</span>的左边缘对齐</span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_alignLeft</span>=<span class="string">&quot;@id/button3&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:text</span>=<span class="string">&quot;Button 1&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="FrameLayout帧布局">FrameLayout帧布局<a class="header-anchor" href="#FrameLayout帧布局"> ¶ </a></h4>
<h4 id="引入布局">引入布局<a class="header-anchor" href="#引入布局"> ¶ </a></h4>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">include</span> <span class="attr">layout</span>=<span class="string">&quot;@layout/title&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="自定义布局">自定义布局<a class="header-anchor" href="#自定义布局"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TitleLayout</span> <span class="keyword">extends</span> <span class="title">LinearLayout</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">TitleLayout</span><span class="params">(Context context, AttributeSet attrs)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(context, attrs);</span><br><span class="line">        LayoutInflater.from(context).inflate(R.layout.title, <span class="keyword">this</span>);</span><br><span class="line">        Button titleBack = (Button) findViewById(R.id.title_back);</span><br><span class="line">        Button titleEdit = (Button) findViewById(R.id.title_edit);</span><br><span class="line">        titleBack.setOnClickListener(<span class="keyword">new</span> OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                ((Activity) getContext()).finish();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        titleEdit.setOnClickListener(<span class="keyword">new</span> OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                Toast.makeText(getContext(), <span class="string">&quot;You clicked Edit button&quot;</span>,</span><br><span class="line">                    Toast.LENGTH_SHORT).show();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="制作9-Patch图片">制作9-Patch图片<a class="header-anchor" href="#制作9-Patch图片"> ¶ </a></h3>
<h2 id="Android-资源">Android 资源<a class="header-anchor" href="#Android-资源"> ¶ </a></h2>
<p>Android中的资源，一般分为两类：</p>
<ul>
<li>
<p>系统内置资源：Android SDK中所提供的已经定义好的资源，用户可以直接拿来使用。</p>
</li>
<li>
<p>用户自定义资源：用户自己定义或引入的，只适用于当前应用的资源。</p>
</li>
</ul>
<h3 id="res目录">res目录<a class="header-anchor" href="#res目录"> ¶ </a></h3>
<p>res目录：可以使用R类访问的资源，放到该目录下。</p>
<table>
<thead>
<tr>
<th>res子目录</th>
<th><strong>可以存放的资源</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>res/anim</td>
<td>定义补间动画的XML文件</td>
</tr>
<tr>
<td>res/color</td>
<td>定义不同状态下颜色列表的XML文件</td>
</tr>
<tr>
<td>res/drawable</td>
<td>各种位图文件（png、jpg、gif、9-Patch）  可以编译成各种drawable对象的XML文件</td>
</tr>
<tr>
<td>res/mipmap</td>
<td>应用程序Launcher图标</td>
</tr>
<tr>
<td>res/layout</td>
<td>用户界面布局文件</td>
</tr>
<tr>
<td>res/menu</td>
<td>菜单资源布局文件（选择菜单、子菜单、上下文菜单）</td>
</tr>
<tr>
<td>res/raw</td>
<td>任意类型的原生资源</td>
</tr>
<tr>
<td>res/values</td>
<td>各种简单值的XML文件（包括字符串、整数、数组、尺寸等）</td>
</tr>
<tr>
<td>res/xml</td>
<td>其它任意的XML文件（可能没有特殊意义的XML文件）</td>
</tr>
</tbody>
</table>
<p>在Android中使用res目录下资源或系统内置资源：</p>
<ul>
<li>在其它资源文件中使用资源：
<ul>
<li>使用res目录下资源：<code>@[&lt;pack_name&gt;:]res_type&gt;/&lt;res_name&gt;</code></li>
<li>使用系统内置资源：<code>@android:&lt;res_type&gt;/&lt;res_name&gt;</code></li>
</ul>
</li>
<li>在Java代码中使用资源：（使用资源的标识符）
<ul>
<li>使用res目录下资源：<code>[&lt;pack_name&gt;.]R.res_type.res_name</code></li>
<li>使用系统内置资源： <code>android.R.res_type.res_name</code></li>
</ul>
</li>
</ul>
<p>getResources()使用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Resources res = getResources();</span><br><span class="line">String appName = res.getString(R.string.app_name);</span><br><span class="line">Drawable drawable </span><br><span class="line">        = res.getDrawable(R.drawable.ic_launcher);</span><br></pre></td></tr></table></figure>
<h4 id="res-values">res/values<a class="header-anchor" href="#res-values"> ¶ </a></h4>
<h5 id="res-values-String-xml">res/values/String.xml<a class="header-anchor" href="#res-values-String-xml"> ¶ </a></h5>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">string</span> <span class="attr">name</span>=<span class="string">&quot;app_name&quot;</span>&gt;</span>HelloWorld<span class="tag">&lt;/<span class="name">string</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">string</span> <span class="attr">name</span>=<span class="string">&quot;user_name&quot;</span>&gt;</span>张三<span class="tag">&lt;/<span class="name">string</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="res-values-colors-xml">res/values/colors.xml<a class="header-anchor" href="#res-values-colors-xml"> ¶ </a></h5>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">color</span> <span class="attr">name</span>=<span class="string">&quot;colorPrimary&quot;</span>&gt;</span>#3F51B5<span class="tag">&lt;/<span class="name">color</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="res-values-dimens-xml">res/values/dimens.xml<a class="header-anchor" href="#res-values-dimens-xml"> ¶ </a></h5>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dimen</span> <span class="attr">name</span>=<span class="string">&quot;view_length&quot;</span>&gt;</span>100dp<span class="tag">&lt;/<span class="name">dimen</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="res-values-array-xml">res/values/array.xml<a class="header-anchor" href="#res-values-array-xml"> ¶ </a></h5>
<p>Array资源可以分为三类：</p>
<ul>
<li>string-array：字符串组成的数组形式。</li>
<li>integer-array：int型数据组成的数组形式。</li>
<li>array：一般数组形式（数据元素类型不限）。</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">string-array</span> <span class="attr">name</span>=<span class="string">&quot;user_name&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">item</span>&gt;</span>张三<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">item</span>&gt;</span>李四<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">string-array</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">integer-array</span> <span class="attr">name</span>=<span class="string">&quot;age&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">item</span>&gt;</span>18<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">item</span>&gt;</span>20<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">integer-array</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">array</span> <span class="attr">name</span>=<span class="string">&quot;pic&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">item</span>&gt;</span>@drawable/user1<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">item</span>&gt;</span>@drawable/user2<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">array</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>java代码中使用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Resources res = getResources();</span><br><span class="line">String[] userName = res.getStringArray(R.array.user_name);</span><br><span class="line"><span class="keyword">int</span>[] age = res.getIntArray(R.array.age);</span><br><span class="line">TypedArray userPic = res.obtainTypedArray(R.array.pic);</span><br><span class="line"><span class="comment">//对于TypedArray类型，需要先获得其TypedArray对象，然后再从该对象中依次获得指定下标的元素。</span></span><br><span class="line"></span><br><span class="line">Drawable firstPic = userPic.getDrawable(<span class="number">0</span>);</span><br></pre></td></tr></table></figure>
<h5 id="res-values-style">res/values/style<a class="header-anchor" href="#res-values-style"> ¶ </a></h5>
<p>Style资源可以设置layout视图组件中某一个视图元素的样式；该资源文件位于res/values目录下，文件名自定义</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span> <span class="attr">name</span>=<span class="string">&quot;CustomText&quot;</span>&gt;</span><span class="xml"></span></span><br><span class="line"><span class="xml">        <span class="tag">&lt;<span class="name">item</span> <span class="attr">name</span>=<span class="string">&quot;android:textSize&quot;</span>&gt;</span>20sp<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span></span><br><span class="line"><span class="xml">        <span class="tag">&lt;<span class="name">item</span> <span class="attr">name</span>=<span class="string">&quot;android:textColor&quot;</span>&gt;</span>#FF4081<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span></span><br><span class="line"><span class="xml">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p><code>&lt;style&gt;</code>元素中parent属性表明该样式继承的父级元素样式。</p>
<p>在布局控件中使用该style</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">TextView</span> <span class="attr">android:layout_width</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;wrap_content&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:text</span>=<span class="string">&quot;Hello World!&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">style</span>=<span class="string">&quot;@style/CustomText&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="res-values-theme">res/values/theme<a class="header-anchor" href="#res-values-theme"> ¶ </a></h5>
<p>Theme资源可以设置Activity窗口的样式；该资源文件位于res/values/目录下，文件名自定义。</p>
<ul>
<li>Theme资源对某个Activity或整个Application起作用，而不是单独的视图组件。</li>
<li>Theme主题主要用来设置应用窗口的特征信息（如窗口标题、窗口背景、窗口边框等）。</li>
</ul>
<p>Theme资源的使用需要从两个角度考虑：</p>
<ul>
<li>在res/values/目录中定义主题资源文件。</li>
<li>在AndroidManifest.xml文件或Activity中为整个Activity或整个Application应用主题</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resources</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span> <span class="attr">name</span>=<span class="string">&quot;CustomTheme&quot;</span> <span class="attr">parent</span>=<span class="string">&quot;AppTheme&quot;</span>&gt;</span><span class="xml"></span></span><br><span class="line"><span class="xml">        <span class="tag">&lt;<span class="name">item</span> <span class="attr">name</span>=<span class="string">&quot;windowNoTitle&quot;</span>&gt;</span>true<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span></span><br><span class="line"><span class="xml">        <span class="tag">&lt;<span class="name">item</span> <span class="attr">name</span>=<span class="string">&quot;android:colorBackground&quot;</span>&gt;</span></span></span><br><span class="line"><span class="xml">                     @color/custom_theme_color<span class="tag">&lt;/<span class="name">item</span>&gt;</span></span></span><br><span class="line"><span class="xml">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resources</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>为应用程序应用主题：</p>
<ul>
<li>在AndroidManifest.xml文件静态绑定：
<ul>
<li>可以为<code>&lt;application&gt;</code>元素添加 <code>android:theme</code>属性，属性值即为用户刚才所设计的theme资源（<code>@style/CustomTheme</code> )。</li>
<li>可以为<code>&lt;activity&gt;</code>元素添加 <code>android:theme</code>属性，属性值即为用户刚才所设计的theme资源（<code>@style/CustomTheme</code> )。</li>
</ul>
</li>
<li>在Activity文件中动态绑定主题：
<ul>
<li>使用Activity类的<code>setTheme( R.style.CustomTheme )</code>方法。</li>
<li>该方法必须在<code>setContentView( )</code>方法或<code>getLayoutInflate( ).inflate( )</code>方法之前被调用。</li>
</ul>
</li>
</ul>
<h5 id="res-mipmap">res/mipmap/<a class="header-anchor" href="#res-mipmap"> ¶ </a></h5>
<p>在res/目录下默认情况有六个mipmap子目录。</p>
<ul>
<li>res/mipmap-anydpi-v26 ： API26及以上使用自适应图标</li>
<li>res/mipmap-mdpi： 中分辨率图标</li>
<li>res/mipmap-hdpi、mipmap-xhdpi、mipmap-xxhdpi、mipmap-xxxhdpi： 高分辨率图标</li>
</ul>
<p>这六个子目录中的图片名可以完全相同，Android应用会根据用户设备分辨率的不同而自行选择。</p>
<h5 id="res-drawable">res/drawable/<a class="header-anchor" href="#res-drawable"> ¶ </a></h5>
<table>
<thead>
<tr>
<th><strong>类型</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Bitmap File</td>
<td>图片文件资源</td>
</tr>
<tr>
<td>9-patch  File</td>
<td>基于适应内容而自动伸缩的图片（扩展名是  .9.png）</td>
</tr>
<tr>
<td>Layer  List</td>
<td>一个XML文件，管理一系列图片资源的特殊资源</td>
</tr>
<tr>
<td>State  List</td>
<td>一个XML文件，针对视图控件不同状态而设置的特殊drawable类型</td>
</tr>
<tr>
<td>Level  List</td>
<td>一个XML文件，根据视图控件不同等级而现实不同的drawable资源</td>
</tr>
<tr>
<td>Shape  Drawable</td>
<td>一个XML文件，定义包含颜色和渐变的几何图形</td>
</tr>
<tr>
<td>Scale  Drawable</td>
<td>一个XML文件，根据当前对准值作相应的平铺处理</td>
</tr>
<tr>
<td>Transition Drawable</td>
<td>一个XML文件，用两张图片形成一个渐变效果的drawable资源</td>
</tr>
</tbody>
</table>
<h5 id="res-xml">res/xml/<a class="header-anchor" href="#res-xml"> ¶ </a></h5>
<p>在res/xml/目录下的XML文件为任意规范的XML文档，这些文档没有其它附加意义，仅仅是存储数据或展示数据。</p>
<p>这些XML文档，不能在其它XML资源中引用。</p>
<p>在Activity中，可以使用Resources对象的getXML()方法，加载到内置的XML解析器中，以方便处理。</p>
<p>该类资源的一个典型应用是：存储应用中使用到的配置信息。</p>
<h5 id="res-raw">res/raw/<a class="header-anchor" href="#res-raw"> ¶ </a></h5>
<p>res/raw/目录存储任意原始格式的文件（可能为.txt、.mp3、.flv等等）。</p>
<p>该目录下的文件，一般不能使用在其它XML资源中。</p>
<p>该目录中的文件，同样会被R类所索引；因此在Activity中可以使用<code>R.raw.***</code>方式引用资源；通过Resources对象的<code>openRawResource()</code>方法，可以获得原始对象的输入流，以方便后续使用。</p>
<h3 id="Assets目录">Assets目录<a class="header-anchor" href="#Assets目录"> ¶ </a></h3>
<p>assets目录：无法直接访问的原生资源（只能通过AssetManager来处理）。</p>
<p>Android Studio创建的项目中，默认不包含assets目录，需要手动创建。在<code>res</code>同级目录创建<code>assets</code>目录</p>
<ul>
<li>assets目录中可以建立子目录，建立更灵活的目录结构。</li>
<li>assets目录中的文件格式是任意的，不一定必须是XML文件。</li>
<li>assets/目录下文件不会被R类索引，即assets/目录下资源不能使用Resources对象获取。</li>
<li>assets/目录下资源不会被打包到APK中，即assets目录中适合存放过大的文件。</li>
<li>assets目录下的资源不会被R类处理，因此不能使用res目录下资源的访问方式来访问。</li>
<li>在Java代码中，一般是通过getAssets( )方法获得AssetManager对象，然后再加载指定资源，处理该资源。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">AssetManager assetManager = getAssets();</span><br><span class="line"><span class="keyword">try</span> &#123;</span><br><span class="line">    InputStream is = assetManager.open(<span class="string">&quot;test.txt&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">    e.printStackTrace();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在Android中使用assets目录下资源：</p>
<ul>
<li>
<p>AssetManager对象中的常用方法：</p>
<table>
<thead>
<tr>
<th><strong>方法名</strong></th>
<th><strong>描述</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>String[] list(String path)</td>
<td>返回path目录下所有文件组成的字符串数组形式（若path为空，则表示assets目录）</td>
</tr>
<tr>
<td>InputStream open(String filename)</td>
<td>打开指定fileName表示的文件流，返回该输入流</td>
</tr>
<tr>
<td>XmlResourceParser  openXmlResourceParser(String filename)</td>
<td>从assets目录下的fileName文件中加载XML解析器</td>
</tr>
<tr>
<td>void close()</td>
<td>关闭当前AssetManager对象</td>
</tr>
</tbody>
</table>
</li>
</ul>
<h2 id="Activity活动">Activity活动<a class="header-anchor" href="#Activity活动"> ¶ </a></h2>
<h3 id="活动基本用法">活动基本用法<a class="header-anchor" href="#活动基本用法"> ¶ </a></h3>
<h4 id="注册活动">注册活动<a class="header-anchor" href="#注册活动"> ¶ </a></h4>
<p>需要在<code>AndroidManifest.xml</code>中的<code>application</code>节点中注册<code>activity</code></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">activity</span> <span class="attr">android:name</span>=<span class="string">&quot;.FirstActivity&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p>若为主Activity</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">activity</span> <span class="attr">android:name</span>=<span class="string">&quot;.FirstActivity&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:label</span>=<span class="string">&quot;This is FirstActivity&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">intent-filter</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">action</span> <span class="attr">android:name</span>=<span class="string">&quot;android.intent.action.MAIN&quot;</span> /&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">category</span> <span class="attr">android:name</span>=<span class="string">&quot;android.intent.category.LAUNCHER&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">intent-filter</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">activity</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="销毁活动">销毁活动<a class="header-anchor" href="#销毁活动"> ¶ </a></h4>
<p>调用<code>finish()</code>方法</p>
<h3 id="使用Intent">使用Intent<a class="header-anchor" href="#使用Intent"> ¶ </a></h3>
<h4 id="显式Intent">显式Intent<a class="header-anchor" href="#显式Intent"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">button1.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">        Intent intent = <span class="keyword">new</span> Intent(FirstActivity.<span class="keyword">this</span>, SecondActivity.class);</span><br><span class="line">        startActivity(intent);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<h4 id="隐式Intent">隐式Intent<a class="header-anchor" href="#隐式Intent"> ¶ </a></h4>
<p>在<code>&lt;action&gt;</code> 标签中我们指明了当前活动可以响应某个action ，而<code>&lt;category&gt;</code> 标签则包含了一些附加信息，更精确地指明了当前的活动能够响应的Intent中还可能带有的category 。只有<code>&lt;action&gt;</code> 和<code>&lt;category&gt;</code> 中的内容同时能够匹配上Intent中指定的<code>action</code> 和<code>category</code> 时，这个活动才能响应该<code>Intent</code>。</p>
<p>可以新建<code>Intent</code>时，直接将<code>action</code>字符串传进去</p>
<p>每个Intent中只能指定一个<code>action</code> ，但却能指定多个<code>category</code> 。</p>
<p>可以使用<code>Intent.addCategory(String category)</code>来指定category，如果没有符合的activity，app就会报错</p>
<p>在<code>&lt;intent-filter&gt;</code>标签中再配置一个<code>&lt;data&gt;</code> 标签，用于更精确地指定当前活动能够响应什么类型的数据。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用系统浏览器打开百度</span></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">    Intent intent = <span class="keyword">new</span> Intent(Intent.ACTION_VIEW);</span><br><span class="line">    intent.setData(Uri.parse(<span class="string">&quot;http://www.baidu.com&quot;</span>));</span><br><span class="line">    startActivity(intent);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我们还可以在<code>&lt;intent-filter&gt;</code> 标签中再配置一个<code>&lt;data&gt;</code> 标签，用于更精确地指定当前活动能够响应什么类型的数据。<code>&lt;data&gt;</code> 标签中主要可以配置以下属性。</p>
<ul>
<li><code>android:scheme</code> 。用于指定数据的协议部分，如上例中的<code>http</code>部分。</li>
<li><code>android:host</code> 。用于指定数据的主机名部分，如上例中的<code>www.baidu.com</code>部分。</li>
<li><code>android:port</code> 。用于指定数据的端口部分，一般紧随在主机名之后。</li>
<li><code>android:path</code> 。用于指定主机名和端口之后的部分，如一段网址中跟在域名之后的内容。</li>
<li><code>android:mimeType</code> 。用于指定可以处理的数据类型，允许使用通配符的方式进行指定。</li>
</ul>
<p>只有<code>&lt;data&gt;</code> 标签中指定的内容和Intent中携带的Data完全一致时，当前活动才能够响应该Intent。</p>
<h4 id="向下一个活动传递数据">向下一个活动传递数据<a class="header-anchor" href="#向下一个活动传递数据"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">button1.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">        String data = <span class="string">&quot;Hello SecondActivity&quot;</span>;</span><br><span class="line">        Intent intent = <span class="keyword">new</span> Intent(FirstActivity.<span class="keyword">this</span>, SecondActivity.class);</span><br><span class="line">        intent.putExtra(<span class="string">&quot;extra_data&quot;</span>, data);</span><br><span class="line">        startActivity(intent);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SecondActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line"></span><br><span class="line">        setContentView(R.layout.second_layout);</span><br><span class="line">        Intent intent = getIntent();</span><br><span class="line">        String data = intent.getStringExtra(<span class="string">&quot;extra_data&quot;</span>);</span><br><span class="line">        Log.d(<span class="string">&quot;SecondActivity&quot;</span>, data);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="返回数据给上一个活动">返回数据给上一个活动<a class="header-anchor" href="#返回数据给上一个活动"> ¶ </a></h4>
<p>启动新activity</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">button1.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">        Intent intent = <span class="keyword">new</span> Intent(FirstActivity.<span class="keyword">this</span>, SecondActivity.class);</span><br><span class="line">        startActivityForResult(intent, <span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<p>新activity返回数据</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">    Intent intent = <span class="keyword">new</span> Intent();</span><br><span class="line">    intent.putExtra(<span class="string">&quot;data_return&quot;</span>, <span class="string">&quot;Hello FirstActivity&quot;</span>);</span><br><span class="line">    setResult(RESULT_OK, intent);</span><br><span class="line">    finish();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>旧activity接收数据</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onActivityResult</span><span class="params">(<span class="keyword">int</span> requestCode, <span class="keyword">int</span> resultCode, Intent data)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span> (requestCode) &#123;</span><br><span class="line">        <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">            <span class="keyword">if</span> (resultCode == RESULT_OK) &#123;</span><br><span class="line">                String returnedData = data.getStringExtra(<span class="string">&quot;data_return&quot;</span>);</span><br><span class="line">                Log.d(<span class="string">&quot;FirstActivity&quot;</span>, returnedData);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>onActivityResult()方法带有三个参数，第一个参数requestCode ，即我们在启动活动时传入的请求码。第二个参数resultCode ，即我们在返回数据时传入的处理结果。第三个参数data ，即携带着返回数据的Intent。由于在一个活动中有可能调用startActivityForResult() 方法去启动很多不同的活动，每一个活动返回的数据都会回调到onActivityResult()这个方法中，因此我们首先要做的就是通过检查requestCode 的值来判断数据来源。确定数据是从SecondActivity返回的之后，我们再通过resultCode 的值来判断处理结果是否成功。最后从data 中取值并打印出来，这样就完成了向上一个活动返回数据的工作。</p>
<p>一般通过重写<code>onBackPressed()</code>方法来返回数据和结束activity</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onBackPressed</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    Intent intent = <span class="keyword">new</span> Intent();</span><br><span class="line">    intent.putExtra(<span class="string">&quot;data_return&quot;</span>, <span class="string">&quot;Hello FirstActivity&quot;</span>);</span><br><span class="line">    setResult(RESULT_OK, intent);</span><br><span class="line">    finish();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="Activity生命周期">Activity生命周期<a class="header-anchor" href="#Activity生命周期"> ¶ </a></h3>
<h4 id="返回栈">返回栈<a class="header-anchor" href="#返回栈"> ¶ </a></h4>
<p>Android中的活动是可以层叠的。我们每启动一个新的活动，就会覆盖在原活动之上，然后点击Back键会销毁最上面的活动，下面的一个活动就会重新显示出来。</p>
<p>Android是使用任务（Task）来管理活动的，一个任务就是一组存放在栈里的活动的集合，这个栈也被称作返回栈（Back Stack）</p>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/%E8%BF%94%E5%9B%9E%E6%A0%88.png" alt="返回栈"></p>
<h4 id="活动状态">活动状态<a class="header-anchor" href="#活动状态"> ¶ </a></h4>
<ol>
<li>
<p>运行状态</p>
<p>当一个活动位于返回栈的<strong>栈顶</strong>时，这时活动就处于运行状态。系统最不愿意回收的就是处于运行状态的活动，因为这会带来非常差的用户体验。</p>
</li>
<li>
<p>暂停状态</p>
<p>当一个活动<strong>不再处于栈顶位置，但仍然可见</strong>时，这时活动就进入了暂停状态。你可能会觉得既然活动已经不在栈顶了，还怎么会可见呢？这是因为并不是每一个活动都会占满整个屏幕的，比如对话框形式的活动只会占用屏幕中间的部分区域，你很快就会在后面看到这种活动。处于暂停状态的活动仍然是完全存活着的，系统也不愿意去回收这种活动（因为它还是可见的，回收可见的东西都会在用户体验方面有不好的影响），只有在内存极低的情况下，系统才会去考虑回收这种活动。</p>
</li>
<li>
<p>停止状态</p>
<p>当一个活动<strong>不再处于栈顶位置，并且完全不可见</strong>的时候，就进入了停止状态。系统<strong>仍然会为这种活动保存相应的状态和成员变量，但是这并不是完全可靠的，当其他地方需要内存时，处于停止状态的活动有可能会被系统回收。</strong></p>
</li>
<li>
<p>销毁状态</p>
<p>当一个活动从返回栈中移除后就变成了销毁状态。系统会最倾向于回收处于这种状态的活动，从而保证手机的内存充足。</p>
</li>
</ol>
<h4 id="活动的生命周期">活动的生命周期<a class="header-anchor" href="#活动的生命周期"> ¶ </a></h4>
<ol>
<li><code>onCreate()</code>:这个方法你已经看到过很多次了，每个活动中我们都重写了这个方法，它会在活动第一次被创建的时候调用。你应该在这个方法中完成活动的初始化操作，比如说加载布局、绑定事件等。</li>
<li><code>onStart()</code>:这个方法在活动由不可见变为可见的时候调用。</li>
<li><code>onResume()</code>:这个方法在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的栈顶，并且处于运行状态。</li>
<li><code>onPause()</code>:这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在这个方法中将一些消耗CPU的资源释放掉，以及保存一些关键数据，但这个方法的执行速度一定要快，不然会影响到新的栈顶活动的使用。</li>
<li><code>onStop()</code>:这个方法在活动完全不可见的时候调用。它和<code>onPause()</code> 方法的主要区别在于，如果启动的新活动是一个对话框式的活动，那么<code>onPause()</code> 方法会得到执行，而<code>onStop()</code> 方法并不会执行。</li>
<li><code>onDestroy()</code>:这个方法在活动被销毁之前调用，之后活动的状态将变为销毁状态。</li>
<li><code>onRestart()</code>:这个方法在活动由停止状态变为运行状态之前调用，也就是活动被重新启动了。<br>
活动的完整周期：</li>
</ol>
<p>活动的初始化，比如布局、绑定事件：onCreate() -&gt; 活动的转为可见：onStart() -&gt; 活动转为可以与用户进行交互：onResume() -&gt; 活动转为不可见并释放相关资源：onPause() -&gt; 活动释放资源：onStop() -&gt; 活动销毁：onDestory()</p>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/activity%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.png" alt="activity生命周期"></p>
<h4 id="活动被回收了怎么办">活动被回收了怎么办<a class="header-anchor" href="#活动被回收了怎么办"> ¶ </a></h4>
<p>onSaveInstanceState() 方法会携带一个Bundle</p>
<p>保存</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onSaveInstanceState</span><span class="params">(Bundle outState)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>.onSaveInstanceState(outState);</span><br><span class="line">    String tempData = <span class="string">&quot;Something you just typed&quot;</span>;</span><br><span class="line">    outState.putString(<span class="string">&quot;data_key&quot;</span>, tempData);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>恢复</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">    Log.d(TAG, <span class="string">&quot;onCreate&quot;</span>);</span><br><span class="line">    setContentView(R.layout.activity_main);</span><br><span class="line">    <span class="keyword">if</span> (savedInstanceState != <span class="keyword">null</span>) &#123;</span><br><span class="line">        String tempData = savedInstanceState.getString(<span class="string">&quot;data_key&quot;</span>);</span><br><span class="line">        Log.d(TAG, tempData);</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="活动的启动模式">活动的启动模式<a class="header-anchor" href="#活动的启动模式"> ¶ </a></h3>
<p>在<code>&lt;activity&gt;</code>节点中指定属性 <code>android:launchMode=&quot;&quot;</code></p>
<ul>
<li>
<p>standard：默认启动模式</p>
<p><strong>standard是活动默认的启动模式</strong>，在不进行显式指定的情况下，所有活动都会自动使用这种启动模式。因此，到目前为止我们写过的所有活动都是使用的standard模式。经过上一节的学习，你已经知道了Android是使用返回栈来管理活动的，</p>
<p>在standard模式（即默认情况）下，每当启动一个新的活动，它就会在返回栈中入栈，并处于栈顶的位置。对于使用standard模式的活动，系统不会在乎这个活动是否已经在返回栈中存在，每次启动都会创建该活动的一个新的实例。</p>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/standard.png" alt="standard"></p>
</li>
<li>
<p>singleTop：顶部不重复</p>
<p>使用singleTop模式。当活动的启动模式指定为singleTop，在启动活动时如果发现返回栈的栈顶已经是该活动，则认为可以直接使用它，不会再创建新的活动实例。</p>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/singleTop.png" alt="singleTop"></p>
</li>
<li>
<p>singleTask：任务栈中不重复</p>
<p>当活动的启动模式指定为singleTask，每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例，如果发现已经存在则直接使用该实例，<strong>并把在这个活动之上的所有活动统统出栈，如果没有发现就会创建一个新的活动实例。</strong></p>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/singleTask.png" alt="singleTask"></p>
</li>
<li>
<p>singleInstance：单独任务栈</p>
<p>在这种模式下会有一个单独的返回栈来管理这个活动，不管是哪个应用程序来访问这个活动，都共用的同一个返回栈</p>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/singleInstance.png" alt="singleInstance"></p>
</li>
</ul>
<h4 id="跨应用启动Activity">跨应用启动Activity<a class="header-anchor" href="#跨应用启动Activity"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Intent intent = <span class="keyword">new</span> Intent();</span><br><span class="line">ComponentName comName = <span class="keyword">new</span> ComponentName([PackageName],[PackageName/ActivityName]);</span><br><span class="line">intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);</span><br><span class="line">intent.setComponent(comName);</span><br><span class="line">startActivity(intent);</span><br></pre></td></tr></table></figure>
<h3 id="活动管理">活动管理<a class="header-anchor" href="#活动管理"> ¶ </a></h3>
<h4 id="了解当前界面对应活动">了解当前界面对应活动<a class="header-anchor" href="#了解当前界面对应活动"> ¶ </a></h4>
<p>创建自己的Activity基类BaseActivity；并让所有activity继承该类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BaseActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        Log.d(<span class="string">&quot;BaseActivity&quot;</span>, getClass().getSimpleName());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>当进入新activity时，会打印当前activity的类名</p>
<h4 id="活动管理器">活动管理器<a class="header-anchor" href="#活动管理器"> ¶ </a></h4>
<p>ActivityCollector</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ActivityCollector</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> List&lt;Activity&gt; activities = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">addActivity</span><span class="params">(Activity activity)</span> </span>&#123;</span><br><span class="line">        activities.add(activity);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">removeActivity</span><span class="params">(Activity activity)</span> </span>&#123;</span><br><span class="line">        activities.remove(activity);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">finishAll</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">for</span> (Activity activity : activities) &#123;</span><br><span class="line">            <span class="keyword">if</span> (!activity.isFinishing()) &#123;</span><br><span class="line">                activity.finish();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        activities.clear();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>BaseActivity</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BaseActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        Log.d(<span class="string">&quot;BaseActivity&quot;</span>, getClass().getSimpleName());</span><br><span class="line">        ActivityCollector.addActivity(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onDestroy();</span><br><span class="line"></span><br><span class="line">        ActivityCollector.removeActivity(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在BaseActivity 的onCreate() 方法中调用了ActivityCollector 的addActivity() 方法，表明将当前正在创建的活动添加到活动管理器里。然后在BaseActivity 中重写onDestroy() 方法，并调用了ActivityCollector 的removeActivity()方法，表明将一个马上要销毁的活动从活动管理器里移除。</p>
<h5 id="退出程序">退出程序<a class="header-anchor" href="#退出程序"> ¶ </a></h5>
<p>不管你想在什么地方退出程序，只需要调用ActivityCollector.finishAll() 方法就可以了</p>
<p>退出后还可以杀调当前进程</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">android.os.Process.killProcess(android.os.Process.myPid());</span><br></pre></td></tr></table></figure>
<h4 id="启动Activity">启动Activity<a class="header-anchor" href="#启动Activity"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">actionStart</span><span class="params">(Context context, String data1, String data2)</span> </span>&#123;</span><br><span class="line">        Intent intent = <span class="keyword">new</span> Intent(context, [current_activity.class]);</span><br><span class="line">        intent.putExtra(<span class="string">&quot;param1&quot;</span>, data1);</span><br><span class="line">        intent.putExtra(<span class="string">&quot;param2&quot;</span>, data2);</span><br><span class="line">        context.startActivity(intent);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>可以快速调用含有该方法的Activity</p>
<h2 id="广播接收者BroadcastReceiver">广播接收者BroadcastReceiver<a class="header-anchor" href="#广播接收者BroadcastReceiver"> ¶ </a></h2>
<h3 id="广播机制简介">广播机制简介<a class="header-anchor" href="#广播机制简介"> ¶ </a></h3>
<ul>
<li>
<pre><code>标准广播 （Normal broadcasts）是一种完全异步执行的广播，在广播发出之后，所有的广播接收器几乎都会在同一时刻接收到这条广播消息，因此它们之间没有任何先后顺序可言。这种广播的效率会比较高，但同时也意味着它是无法被截断的。
</code></pre>
</li>
<li>
<pre><code>有序广播 （Ordered broadcasts）则是一种同步执行的广播，在广播发出之后，同一时刻只会有一个广播接收器能够收到这条广播消息，当这个广播接收器中的逻辑执行完毕后，广播才会继续传递。所以此时的广播接收器是有先后顺序的，优先级高的广播接收器就可以先收到广播消息，并且前面的广播接收器还可以截断正在传递的广播，这样后面的广播接收器就无法收到广播消息了。
</code></pre>
</li>
</ul>
<h3 id="接收系统广播">接收系统广播<a class="header-anchor" href="#接收系统广播"> ¶ </a></h3>
<h4 id="动态注册监听网络变化">动态注册监听网络变化<a class="header-anchor" href="#动态注册监听网络变化"> ¶ </a></h4>
<p>新建一个类，让它继承自<code>BroadcastReceiver</code> ，并重写父类的<code>onReceive()</code> 方法。当有广播到来时，<code>onReceive()</code> 方法就会得到执行</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> IntentFilter intentFilter;</span><br><span class="line">    <span class="keyword">private</span> NetworkChangeReceiver networkChangeReceiver;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        <span class="comment">// 创建一个intent过滤器</span></span><br><span class="line">        intentFilter = <span class="keyword">new</span> IntentFilter();</span><br><span class="line">        <span class="comment">// 添加想要接收的intent请求</span></span><br><span class="line">        intentFilter.addAction(<span class="string">&quot;android.net.conn.CONNECTIVITY_CHANGE&quot;</span>);</span><br><span class="line">        <span class="comment">// 实例化 Receiver类</span></span><br><span class="line">        networkChangeReceiver = <span class="keyword">new</span> NetworkChangeReceiver();</span><br><span class="line">        <span class="comment">// 动态注册广播接收者</span></span><br><span class="line">        registerReceiver(networkChangeReceiver, intentFilter);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onDestroy();</span><br><span class="line">        <span class="comment">// 取消注册广播接收者</span></span><br><span class="line">        unregisterReceiver(networkChangeReceiver);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">NetworkChangeReceiver</span> <span class="keyword">extends</span> <span class="title">BroadcastReceiver</span> </span>&#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceive</span><span class="params">(Context context, Intent intent)</span> </span>&#123;</span><br><span class="line">            <span class="comment">// 当收到广播时，弹窗提示网络状态改变</span></span><br><span class="line">            Toast.makeText(context, <span class="string">&quot;network changes&quot;</span>, Toast.LENGTH_SHORT).show();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>或者当网络状态改变时，提示当前有网络还是无网络</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">NetworkChangeReceiver</span> <span class="keyword">extends</span> <span class="title">BroadcastReceiver</span> </span>&#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceive</span><span class="params">(Context context, Intent intent)</span> </span>&#123;</span><br><span class="line">            <span class="comment">// 得到ConnectivityManager实例(一个系统服务类，专门用于管理网络连接)</span></span><br><span class="line">            ConnectivityManager connectionManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);</span><br><span class="line">            <span class="comment">// 得到NetworkInfo的实例</span></span><br><span class="line">            NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();</span><br><span class="line">            <span class="comment">// 通过调用NetworkInfo的isAvailable()方法，来判断出当前有无网络</span></span><br><span class="line">            <span class="keyword">if</span> (networkInfo != <span class="keyword">null</span> &amp;&amp; networkInfo.isAvailable()) &#123;</span><br><span class="line">                Toast.makeText(context, <span class="string">&quot;network is available&quot;</span>,</span><br><span class="line">                    Toast.LENGTH_SHORT).show();</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                Toast.makeText(context, <span class="string">&quot;network is unavailable&quot;</span>,</span><br><span class="line">                    Toast.LENGTH_SHORT).show();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>同时，访问网络状态需要在<code>AndroidManifest.xml</code>中声明权限</p>
<h4 id="静态注册实现开机启动提醒">静态注册实现开机启动提醒<a class="header-anchor" href="#静态注册实现开机启动提醒"> ¶ </a></h4>
<p>需要在<code>AndroidManifest.xml</code>中注册receiver</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">receiver</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:name</span>=<span class="string">&quot;.BootCompleteReceiver&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:enabled</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:exported</span>=<span class="string">&quot;true&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">intent-filter</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 开机事件广播 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">action</span> <span class="attr">android:name</span>=<span class="string">&quot;android.intent.action.BOOT_COMPLETED&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">intent-filter</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">receiver</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>同时需要添加相应监听开机的权限</p>
<p>之后便可以添加一个Receiver.java，并在<code>onReceive()</code>中编写相应控制逻辑</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BootCompleteReceiver</span> <span class="keyword">extends</span> <span class="title">BroadcastReceiver</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceive</span><span class="params">(Context context, Intent intent)</span> </span>&#123;</span><br><span class="line">        Toast.makeText(context, <span class="string">&quot;Boot Complete&quot;</span>, Toast.LENGTH_LONG).show();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>不要在<code>onReceive()</code> 方法中添加过多的逻辑或者进行任何的耗时操作，因为在广播接收器中是不允许开启线程的，当<code>onReceive()</code> 方法运行了较长时间而没有结束时，程序就会报错。</p>
<h4 id="发送自定义广播">发送自定义广播<a class="header-anchor" href="#发送自定义广播"> ¶ </a></h4>
<h5 id="发送标准广播">发送标准广播<a class="header-anchor" href="#发送标准广播"> ¶ </a></h5>
<h6 id="定义一个自己的广播接收器">定义一个自己的广播接收器<a class="header-anchor" href="#定义一个自己的广播接收器"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyBroadcastReceiver</span> <span class="keyword">extends</span> <span class="title">BroadcastReceiver</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceive</span><span class="params">(Context context, Intent intent)</span> </span>&#123;</span><br><span class="line">        Toast.makeText(context, <span class="string">&quot;received in MyBroadcastReceiver&quot;</span>, Toast.LENGTH_</span><br><span class="line">            SHORT).show();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">receiver</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:name</span>=<span class="string">&quot;.MyBroadcastReceiver&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:enabled</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:exported</span>=<span class="string">&quot;true&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">intent-filter</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">action</span> <span class="attr">android:name</span>=<span class="string">&quot;com.example.broadcasttest.MY_BROADCAST&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">intent-filter</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">receiver</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>接收一个值为<code>com.example.broadcasttest.MY_BROADCAST</code>的广播</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">    Intent intent = <span class="keyword">new</span> Intent(<span class="string">&quot;com.example.broadcasttest.MY_BROADCAST&quot;</span>);</span><br><span class="line">    sendBroadcast(intent);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 同</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">    Intent intent = <span class="keyword">new</span> Intent();</span><br><span class="line">    intent.setAction(<span class="string">&quot;com.example.broadcasttest.MY_BROADCAST&quot;</span>);</span><br><span class="line">    intent.setPackage(<span class="string">&quot;com.example.broadcasttest&quot;</span>);</span><br><span class="line">    sendBroadcast(intent);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>由于广播是使用Intent进行传递的，因此你还可以在Intent中携带一些数据传递给广播接收器。</p>
<h5 id="发送有序广播">发送有序广播<a class="header-anchor" href="#发送有序广播"> ¶ </a></h5>
<p>发送时</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">    Intent intent = <span class="keyword">new</span></span><br><span class="line">        Intent(<span class="string">&quot;com.example.broadcasttest.MY_BROADCAST&quot;</span>);</span><br><span class="line">    sendOrderedBroadcast(intent, <span class="keyword">null</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接收时，通过<code>android.priority</code>属性来设置优先级</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">receiver</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:name</span>=<span class="string">&quot;.MyBroadcastReceiver&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:enabled</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:exported</span>=<span class="string">&quot;true&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">intent-filter</span> <span class="attr">android:priority</span>=<span class="string">&quot;100&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">action</span> <span class="attr">android:name</span>=<span class="string">&quot;com.example.broadcasttest.MY_BROADCAST&quot;</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">intent-filter</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">receiver</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>同时通过<code>abortBroadcast()</code>方法来截断广播（之后的广播接收器无法收到）</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceive</span><span class="params">(Context context, Intent intent)</span> </span>&#123;</span><br><span class="line">    Toast.makeText(context, <span class="string">&quot;received in MyBroadcastReceiver&quot;</span>,</span><br><span class="line">        Toast.LENGTH_SHORT).show();</span><br><span class="line">    abortBroadcast();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="使用本地广播">使用本地广播<a class="header-anchor" href="#使用本地广播"> ¶ </a></h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> IntentFilter intentFilter;</span><br><span class="line">    <span class="keyword">private</span> LocalReceiver localReceiver;</span><br><span class="line">    <span class="keyword">private</span> LocalBroadcastManager localBroadcastManager;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        localBroadcastManager = LocalBroadcastManager.getInstance(<span class="keyword">this</span>); <span class="comment">// 获取实例</span></span><br><span class="line">        Button button = (Button) findViewById(R.id.button);</span><br><span class="line">        button.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">                Intent intent = <span class="keyword">new</span> Intent(<span class="string">&quot;com.example.broadcasttest.LOCAL_BROADCAST&quot;</span>);</span><br><span class="line">                localBroadcastManager.sendBroadcast(intent); <span class="comment">// 发送本地广播</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        intentFilter = <span class="keyword">new</span> IntentFilter();</span><br><span class="line">        intentFilter.addAction(<span class="string">&quot;com.example.broadcasttest.LOCAL_BROADCAST&quot;</span>);</span><br><span class="line">        localReceiver = <span class="keyword">new</span> LocalReceiver();</span><br><span class="line">        localBroadcastManager.registerReceiver(localReceiver, intentFilter); <span class="comment">// 注</span></span><br><span class="line">        册本地广播监听器</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onDestroy();</span><br><span class="line">        localBroadcastManager.unregisterReceiver(localReceiver);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">LocalReceiver</span> <span class="keyword">extends</span> <span class="title">BroadcastReceiver</span> </span>&#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceive</span><span class="params">(Context context, Intent intent)</span> </span>&#123;</span><br><span class="line">            Toast.makeText(context, <span class="string">&quot;received local broadcast&quot;</span>, Toast.LENGTH_SHORT).</span><br><span class="line"></span><br><span class="line">               show();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>与动态注册广播接收器一样，不过现在是通过<code>LocalBroadcastManager</code>的<code>getInstance()</code> 方法得到了它的一个实例，然后在注册广播接收器的时候调用的是<code>LocalBroadcastManager</code>的<code>registerReceiver()</code> 方法，在发送广播的时候调用的是<code>LocalBroadcastManager</code>的<code>sendBroadcast()</code> 方法</p>
<p><strong>本地广播是无法通过静态注册的方式来接收</strong></p>
<h3 id="使用广播来实现强制下线功能">使用广播来实现强制下线功能<a class="header-anchor" href="#使用广播来实现强制下线功能"> ¶ </a></h3>
<p>@TODO</p>
<h2 id="数据存储-持久化技术">数据存储 持久化技术<a class="header-anchor" href="#数据存储-持久化技术"> ¶ </a></h2>
<h3 id="文件存储">文件存储<a class="header-anchor" href="#文件存储"> ¶ </a></h3>
<ul>
<li>Context 类中提供了一个openFileOutput() 方法，可以用于将数据存储到指定的文件中。
<ul>
<li>第一个参数为文件名（默认存储到<code>/data/data/&lt;package name&gt;/files/</code>目录下）</li>
<li>第二个参数是文件的操作模式，主要有两种模式可选，MODE_PRIVATE和MODE_APPEND。其中MODE_PRIVATE是默认的操作模式，表示当指定同样文件名的时候，所写入的内容将会覆盖原文件中的内容，而MODE_APPEND则表示如果该文件已存在，就往文件里面追加内容，不存在就创建新文件。</li>
<li>返回的是一个FileOutputStream 对象</li>
</ul>
</li>
<li>Context 类中还提供了一个openFileInput() 方法，用于从文件中读取数据。
<ul>
<li>只接收一个参数，即要读取的文件名</li>
</ul>
</li>
</ul>
<h3 id="SD卡文件读写">SD卡文件读写<a class="header-anchor" href="#SD卡文件读写"> ¶ </a></h3>
<ol>
<li>
<p>判断是否手机插入SD卡，并且程序有读写SD卡的权限。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Environment.getExternalStorageState().equals(android</span><br><span class="line">        .os.Environment.MEDIA_MOUNTED);</span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li>
<p>获得SD卡目录：getExternalFilesDir(“类型&quot; )</p>
<p>“类型”参数：可为null或右图所列</p>
<ul>
<li>null：表示sdcard/data/android/包名/files</li>
<li>Enviroment.DIRECTORY_DCIM(或“DCIM”)：表示sdcard/data/android/包名/files/DCIM</li>
</ul>
</li>
</ol>
<p>手机插入SD卡，在AVD中通过mksdcard命令来创建。</p>
<p>获得读写SD卡的权限需要在AndroidManifest.xml中添加读写权限。</p>
<h3 id="SharedPreferences存储">SharedPreferences存储<a class="header-anchor" href="#SharedPreferences存储"> ¶ </a></h3>
<p>SharedPreferences文件是使用XML格式来对数据进行管理的。</p>
<h4 id="将数据存储到SharedPreferences中">将数据存储到SharedPreferences中<a class="header-anchor" href="#将数据存储到SharedPreferences中"> ¶ </a></h4>
<h5 id="获取SharedPreferences对象">获取SharedPreferences对象<a class="header-anchor" href="#获取SharedPreferences对象"> ¶ </a></h5>
<ul>
<li>Context 类中的getSharedPreferences() 方法
<ul>
<li>第一个参数用于指定SharedPreferences文件的名称，如果指定的文件不存在则会创建一个，SharedPreferences文件都是存放在<code>/data/data/&lt;package name&gt;/shared_prefs/</code>目录下</li>
<li>第二个参数用于指定操作模式，目前只有MODE_PRIVATE这一种模式可选，它是默认的操作模式，和直接传入<code>0</code>效果是相同的，表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。其他几种操作模式均已被废弃</li>
</ul>
</li>
<li>Activity 类中的getPreferences() 方法
<ul>
<li>它只接收一个操作模式参数。会自动将当前活动的类名作为SharedPreferences的文件名。</li>
</ul>
</li>
<li>PreferenceManager 类中的getDefaultSharedPreferences() 方法
<ul>
<li>这是一个静态方法，它接收一个Context 参数，并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件</li>
</ul>
</li>
</ul>
<h5 id="使用对象进行存储">使用对象进行存储<a class="header-anchor" href="#使用对象进行存储"> ¶ </a></h5>
<ol>
<li>调用SharedPreferences 对象的edit() 方法来获取一个SharedPreferences.Editor 对象。</li>
<li>向SharedPreferences.Editor 对象中添加数据，比如添加一个布尔型数据就使用putBoolean() 方法，添加一个字符串则使用putString() 方法，以此类推。</li>
<li>调用apply() 方法将添加的数据提交，从而完成数据存储操作。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">SharedPreferences.Editor editor = getSharedPreferences(<span class="string">&quot;data&quot;</span>, MODE_PRIVATE).edit();</span><br><span class="line">editor.putString(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;Tom&quot;</span>);</span><br><span class="line">editor.putInt(<span class="string">&quot;age&quot;</span>, <span class="number">28</span>);</span><br><span class="line">editor.putBoolean(<span class="string">&quot;married&quot;</span>, <span class="keyword">false</span>);</span><br><span class="line">editor.apply();</span><br></pre></td></tr></table></figure>
<h4 id="从SharedPreferences中读取数据">从SharedPreferences中读取数据<a class="header-anchor" href="#从SharedPreferences中读取数据"> ¶ </a></h4>
<p>获得<code>SharedPreferences</code>对象后调用相应的<code>getString() 、getInt() 和getBoolean() </code>方法来获取</p>
<h3 id="SQLite数据库存储">SQLite数据库存储<a class="header-anchor" href="#SQLite数据库存储"> ¶ </a></h3>
<h4 id="创建数据库">创建数据库<a class="header-anchor" href="#创建数据库"> ¶ </a></h4>
<p>提供了一个SQLiteOpenHelper帮助类，借助这个类就可以非常简单地对数据库进行创建和升级。SQLiteOpenHelper是一个抽象类</p>
<p>SQLiteOpenHelper中有两个抽象方法，分别是onCreate() 和onUpgrade() ，我们必须在自己的帮助类里面重写这两个方法，然后分别在这两个方法中去实现创建、升级数据库的逻辑。</p>
<p>SQLiteOpenHelper中还有两个非常重要的实例方法：getReadableDatabase() 和getWritableDatabase() 。这两个方法都可以创建或打开一个现有的数据库（如果数据库已存在则直接打开，否则创建一个新的数据库），并返回一个可对数据库进行读写操作的对象。</p>
<p>不同的是，当数据库不可写入的时候getReadableDatabase() 方法返回的对象将以只读的方式去打开数据库，而getWritableDatabase() 方法则将出现异常。</p>
<h5 id="SQLiteOpenHelper构造方法">SQLiteOpenHelper构造方法<a class="header-anchor" href="#SQLiteOpenHelper构造方法"> ¶ </a></h5>
<ul>
<li>较少参数构造方法接收4个参数
<ul>
<li>第一个参数是<strong>Context</strong></li>
<li>第二个参数是<strong>数据库名</strong>，创建数据库时使用的就是这里指定的名称。</li>
<li>第三个参数允许我们在查询数据的时候返回一个自定义的Cursor，<strong>一般都是传入null</strong> 。</li>
<li>第四个参数表示<strong>当前数据库的版本号</strong>，可用于对数据库进行升级操作。</li>
<li>构建出SQLiteOpenHelper的实例之后，再调用它的getReadableDatabase() 或getWritableDatabase() 方法就能够创建数据库了，数据库文件会存放在<code>/data/data/ &lt;package name&gt;/databases/</code>目录下。</li>
<li>此时，重写的onCreate() 方法也会得到执行，所以通常会在这里去处理一些创建表的逻辑。</li>
</ul>
</li>
</ul>
<p>SQLite不像其他的数据库拥有众多繁杂的数据类型，它的数据类型很简单，integer 表示整型，real 表示浮点型，text 表示文本类型，blob 表示二进制类</p>
<h5 id="使用SQLiteOpenHelper实现类">使用SQLiteOpenHelper实现类<a class="header-anchor" href="#使用SQLiteOpenHelper实现类"> ¶ </a></h5>
<p>直接new 实现类，当数据库不存在时，onCreate()会被执行；当构造方法版本号大于原先版本号时，onUpgrade()会被执行</p>
<h4 id="获取数据库对象">获取数据库对象<a class="header-anchor" href="#获取数据库对象"> ¶ </a></h4>
<p>调用SQLiteOpenHelper的getReadableDatabase() 或getWritableDatabase() 方法是可以用于创建和升级数据库的。</p>
<p>这两个方法还都会返回一个QLiteDatabase 对象，借助这个对象就可以对数据进行CRUD操作了。</p>
<p>或者使用<code>SQLiteDatabase.openOrCreateDatabse(dbName,null)</code>来获取</p>
<h4 id="添加数据">添加数据<a class="header-anchor" href="#添加数据"> ¶ </a></h4>
<ul>
<li>SQLiteDatabase 中提供了一个insert() 方法，这个方法就是专门用于添加数据的。
<ul>
<li>第一个参数是表名，我们希望向哪张表里添加数据，这里就传入该表的名字。</li>
<li>第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值NULL ，一般我们用不到这个功能，直接传入null 即可。</li>
<li>第三个参数是一个ContentValues 对象，它提供了一系列的put() 方法重载，用于向ContentValues 中添加数据，只需要将表中的每个列名以及相应的待<br>
添加数据传入即可。</li>
</ul>
</li>
</ul>
<h4 id="更新数据">更新数据<a class="header-anchor" href="#更新数据"> ¶ </a></h4>
<ul>
<li>SQLiteDatabase 中也提供了一个非常好用的update() 方法，用于对数据进行更新，这个方法接收4个参数
<ul>
<li>第一个参数和insert() 方法一样，也是表名，在这里指定去更新哪张表里的数据。</li>
<li>第二个参数是ContentValues 对象，要把更新数据在这里组装进去。</li>
<li>第三、第四个参数用于约束更新某一行或某几行中的数据，不指定的话默认就是更新所有行。==第三参数相当于where部分，第四参数为<code>new String[]</code>为第三参数的占位符提供内容==</li>
</ul>
</li>
</ul>
<h4 id="删除数据">删除数据<a class="header-anchor" href="#删除数据"> ¶ </a></h4>
<ul>
<li>SQLiteDatabase 中提供了一个delete() 方法，专门用于删除数据，这个方法接收3个参数</li>
<li>第一个参数仍然是表名</li>
<li>第二、第三个参数又是用于约束删除某一行或某几行的数据，不指定的话默认就是删除所有行。</li>
</ul>
<h4 id="查询数据">查询数据<a class="header-anchor" href="#查询数据"> ¶ </a></h4>
<ul>
<li>SQLiteDatabase中还提供了一个query() 方法用于对数据进行查询。这个方法的参数非常复杂，最短的一个方法重载也需要传入7个参数。
<ul>
<li>第一个参数，表名，表示我们希望从哪张表中查询数据。</li>
<li>第二个参数用于指定去查询哪几列，如果不指定则默认查询所有列。</li>
<li>第三、第四个参数用于约束查询某一行或某几行的数据，不指定则默认查询所有行的数据。</li>
<li>第五个参数用于指定需要去group by的列，不指定则表示不对查询结果进行groupby操作。</li>
<li>第六个参数用于对group by之后的数据进行进一步的过滤，不指定则表示不进行过滤。</li>
<li>第七个参数用于指定查询结果的排序方式，不指定则表示使用默认的排序方式。</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th style="text-align:center">query()方法参数</th>
<th style="text-align:center">对应SQL部分</th>
<th style="text-align:center">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">table</td>
<td style="text-align:center">from table_name</td>
<td style="text-align:center">指定查询的表名</td>
</tr>
<tr>
<td style="text-align:center">columns</td>
<td style="text-align:center">select column1, column2</td>
<td style="text-align:center">指定查询的列名</td>
</tr>
<tr>
<td style="text-align:center">selection</td>
<td style="text-align:center">where column = value</td>
<td style="text-align:center">指定where 的约束条件</td>
</tr>
<tr>
<td style="text-align:center">selectionArgs</td>
<td style="text-align:center"></td>
<td style="text-align:center">为where 中的占位符提供具体的值</td>
</tr>
<tr>
<td style="text-align:center">groupBy</td>
<td style="text-align:center">group by column</td>
<td style="text-align:center">指定需要group by 的列</td>
</tr>
<tr>
<td style="text-align:center">having</td>
<td style="text-align:center">having column = value</td>
<td style="text-align:center">对group by 后的结果进一步约束</td>
</tr>
<tr>
<td style="text-align:center">orderBy</td>
<td style="text-align:center">order by column1, column2</td>
<td style="text-align:center">指定查询结果的排序方式</td>
</tr>
</tbody>
</table>
<p>调用query() 方法后会返回一个Cursor 对象，查询到的所有数据都将从这个对象中取出。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 查询Book表中所有的数据</span></span><br><span class="line">Cursor cursor = db.query(<span class="string">&quot;Book&quot;</span>, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>);</span><br><span class="line"><span class="keyword">if</span> (cursor.moveToFirst()) &#123;</span><br><span class="line">    <span class="keyword">do</span> &#123;</span><br><span class="line">        <span class="comment">// 遍历Cursor对象，取出数据并打印</span></span><br><span class="line">        String name = cursor.getString(cursor.getColumnIndex</span><br><span class="line">            (<span class="string">&quot;name&quot;</span>));</span><br><span class="line">        String author = cursor.getString(cursor.getColumnIndex</span><br><span class="line">            (<span class="string">&quot;author&quot;</span>));</span><br><span class="line">        <span class="keyword">int</span> pages = cursor.getInt(cursor.getColumnIndex(<span class="string">&quot;pages&quot;</span>));</span><br><span class="line">        <span class="keyword">double</span> price = cur</span><br><span class="line">            (<span class="string">&quot;price&quot;</span>));</span><br><span class="line">    &#125; <span class="keyword">while</span> (cursor.moveToNext());</span><br><span class="line">&#125;</span><br><span class="line">cursor.close();</span><br></pre></td></tr></table></figure>
<h5 id="Cursor类方法">Cursor类方法<a class="header-anchor" href="#Cursor类方法"> ¶ </a></h5>
<table>
<thead>
<tr>
<th>方法名称</th>
<th>方法描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>getCount()</td>
<td>获得总的数据项数</td>
</tr>
<tr>
<td>isFirst()</td>
<td>判断是否第一条记录</td>
</tr>
<tr>
<td>isLast()</td>
<td>判断是否最后一条记录</td>
</tr>
<tr>
<td>moveToFirst()</td>
<td>移动到第一条记录</td>
</tr>
<tr>
<td>moveToLast()</td>
<td>移动到最后一条记录</td>
</tr>
<tr>
<td>move(int  offset)</td>
<td>移动到指定记录</td>
</tr>
<tr>
<td>moveToNext()</td>
<td>移动到下一条记录</td>
</tr>
<tr>
<td>moveToPrevious()</td>
<td>移动到上一条记录</td>
</tr>
<tr>
<td>getColumnIndexOrThrow(String columnName)</td>
<td>根据列名称获得列索引</td>
</tr>
<tr>
<td>getInt(int  columnIndex)</td>
<td>获得指定列索引的int类型值</td>
</tr>
<tr>
<td>getString(int  columnIndex)</td>
<td>获得指定列缩影的String类型值</td>
</tr>
</tbody>
</table>
<h4 id="使用SQL操作数据库">使用SQL操作数据库<a class="header-anchor" href="#使用SQL操作数据库"> ¶ </a></h4>
<ul>
<li>
<p>添加数据的方法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">db.execSQL(<span class="string">&quot;insert into Book (name, author, pages, price) values(?, ?, ?, ?)&quot;</span>,</span><br><span class="line">            <span class="keyword">new</span> String[] &#123; <span class="string">&quot;The Da Vinci Code&quot;</span>, <span class="string">&quot;Dan Brown&quot;</span>, <span class="string">&quot;454&quot;</span>, <span class="string">&quot;16.96&quot;</span> &#125;);</span><br><span class="line">db.execSQL(<span class="string">&quot;insert into Book (name, author, pages, price) values(?, ?, ?, ?)&quot;</span>,</span><br><span class="line">            <span class="keyword">new</span> String[] &#123; <span class="string">&quot;The Lost Symbol&quot;</span>, <span class="string">&quot;Dan Brown&quot;</span>, <span class="string">&quot;510&quot;</span>, <span class="string">&quot;19.95&quot;</span> &#125;);</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>更新数据的方法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.execSQL(<span class="string">&quot;update Book set price = ? where name = ?&quot;</span>, <span class="keyword">new</span> String[] &#123; <span class="string">&quot;10.99&quot;</span>, <span class="string">&quot;The Da Vinci Code&quot;</span> &#125;);</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>删除数据的方法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.execSQL(<span class="string">&quot;delete from Book where pages &gt; ?&quot;</span>, <span class="keyword">new</span> String[] &#123; <span class="string">&quot;500&quot;</span> &#125;);</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>查询数据的方法如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">db.rawQuery(<span class="string">&quot;select * from Book&quot;</span>, <span class="keyword">null</span>);</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>可以看到，除了查询数据的时候调用的是SQLiteDatabase的rawQuery() 方法，其他的操作都是调用的execSQL() 方法。</p>
<h3 id="使用LitePal操作数据库">使用LitePal操作数据库<a class="header-anchor" href="#使用LitePal操作数据库"> ¶ </a></h3>
<p>LitePal是一款开源的Android数据库框架，它采用了对象关系映射（ORM）的模式，并将我们平时开发最常用到的一些数据库功能进行了封装，使得不用编写一行SQL语句就可以完成各种建表和増删改查的操作。LitePal的项目主页上也有详细的使用文档，地址是：<a target="_blank" rel="noopener" href="https://github.com/guolindev/LitePal">guolindev/LitePal: An Android library that makes developers use SQLite database extremely easy. (github.com)</a>。</p>
<h4 id="配置LitePal">配置LitePal<a class="header-anchor" href="#配置LitePal"> ¶ </a></h4>
<h5 id="1-添加LitePal依赖">1. 添加LitePal依赖<a class="header-anchor" href="#1-添加LitePal依赖"> ¶ </a></h5>
<p>就是编辑<code>app/build.gradle</code>文件，在dependencies闭包中添加如下内容</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">dependencies &#123;</span><br><span class="line">    <span class="function">compile <span class="title">fileTree</span><span class="params">(dir: <span class="string">&#x27;libs&#x27;</span>, include: [<span class="string">&#x27;*.jar&#x27;</span>])</span></span></span><br><span class="line"><span class="function">    compile &#x27;com.android.support:appcompat-v7:23.2.0&#x27;</span></span><br><span class="line"><span class="function">    testCompile &#x27;junit:junit:4.12&#x27;</span></span><br><span class="line"><span class="function">    compile &#x27;org.litepal.android:core:1.4.1&#x27;</span></span><br><span class="line"><span class="function">&#125;</span></span><br></pre></td></tr></table></figure>
<h5 id="2-配置litepal-xml文件">2. 配置litepal.xml文件<a class="header-anchor" href="#2-配置litepal-xml文件"> ¶ </a></h5>
<p>右击<code>app/src/main</code>目录→<code>New</code>→<code>Directory</code>，创建一个<code>assets</code>目录，然后在assets目录下再新建一个litepal.xml文件，接着编辑litepal.xml文件中的内容</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">litepal</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dbname</span> <span class="attr">value</span>=<span class="string">&quot;BookStore&quot;</span> &gt;</span><span class="tag">&lt;/<span class="name">dbname</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span> <span class="attr">value</span>=<span class="string">&quot;1&quot;</span> &gt;</span><span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">list</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">list</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">litepal</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li><code>&lt;dbname&gt;</code>标签用于指定数据库名</li>
<li><code>&lt;version&gt;</code> 标签用于指定数据库版本号</li>
<li><code>&lt;list&gt;</code>标签用于指定所有的映射模型</li>
</ul>
<h5 id="3-配置LitePalApplication">3. 配置LitePalApplication<a class="header-anchor" href="#3-配置LitePalApplication"> ¶ </a></h5>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">manifest</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">package</span>=<span class="string">&quot;com.example.litepaltest&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">application</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:name</span>=<span class="string">&quot;org.litepal.LitePalApplication&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:allowBackup</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:icon</span>=<span class="string">&quot;@mipmap/ic_launcher&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:label</span>=<span class="string">&quot;@string/app_name&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:supportsRtl</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:theme</span>=<span class="string">&quot;@style/AppTheme&quot;</span>&gt;</span></span><br><span class="line">        ...</span><br><span class="line">    <span class="tag">&lt;/<span class="name">application</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">manifest</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>将项目的<code>application</code>配置为<code>org.litepal.LitePalApplication</code>，这样才能让LitePal的所有功能都可以正常工作</p>
<h4 id="创建和升级数据库">创建和升级数据库<a class="header-anchor" href="#创建和升级数据库"> ¶ </a></h4>
<p>创建Book类，定义好相关属性（表的列名）</p>
<p>在<code>litepal.xml</code>的<code>&lt;list&gt;</code>标签内添加<code>&lt;mapping class=&quot;com.example.litepaltest.Book&quot;&gt;&lt;/mapping&gt;</code></p>
<h4 id="使用LitePal添加数据">使用LitePal添加数据<a class="header-anchor" href="#使用LitePal添加数据"> ¶ </a></h4>
<p>LitePal进行表管理操作时不需要模型类有任何的继承结构，但是进行CRUD操作时就不行了，必须要让 相关表类 继承自DataSupport 类才行，如Book表需要让Book类继承<code>DataSupport</code>类，然后调用<code>.save()</code>方法将数据存入数据库</p>
<h4 id="使用LitePal更新数据">使用LitePal更新数据<a class="header-anchor" href="#使用LitePal更新数据"> ¶ </a></h4>
<p>对于LitePal来说，对象是否已存储就是根据调用model.isSaved() 方法的结果来判断的，返回true 就表示已存储，返回false 就表示未存储。</p>
<p>方法一：对已存储的对象，重新调用<code>.save()</code>方法进行更新</p>
<p>方法二：更新从数据库中查到的对象</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    Book book = <span class="keyword">new</span> Book();</span><br><span class="line">    book.setPrice(<span class="number">14.95</span>);</span><br><span class="line">    book.setPress(<span class="string">&quot;Anchor&quot;</span>);</span><br><span class="line">    book.updateAll(<span class="string">&quot;name = ? and author = ?&quot;</span>, <span class="string">&quot;The Lost Symbol&quot;</span>, <span class="string">&quot;Dan</span></span><br><span class="line"><span class="string">        Brown&quot;</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>**想把一个字段的值更新成默认值时，是不可以使用上面的方式来set 数据的。**将为数据更新成默认值的操作，LitePal统一提供了一个setToDefault() 方法，然后传入相应的列名就可以实现了。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Book book = <span class="keyword">new</span> Book();</span><br><span class="line">book.setToDefault(<span class="string">&quot;pages&quot;</span>);</span><br><span class="line">book.updateAll();</span><br></pre></td></tr></table></figure>
<h4 id="使用LitePal删除数据">使用LitePal删除数据<a class="header-anchor" href="#使用LitePal删除数据"> ¶ </a></h4>
<ul>
<li>
<p>方法一</p>
<p>调用过save() 方法的对象，或者是通过LitePal提供的查询API查出来的对象，都是可以直接使用delete() 方法来删除数据的。</p>
</li>
<li>
<p>方法二</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DataSupport.deleteAll(Book.class, <span class="string">&quot;price &lt; ?&quot;</span>, <span class="string">&quot;15&quot;</span>);</span><br></pre></td></tr></table></figure>
<p>这里调用了DataSupport.deleteAll() 方法来删除数据，其中deleteAll() 方法的第一个参数用于指定删除哪张表中的数据，Book.class就意味着删除Book表中的数据，后面的参数用于指定约束条件。</p>
</li>
</ul>
<h4 id="使用LitePal查询数据">使用LitePal查询数据<a class="header-anchor" href="#使用LitePal查询数据"> ¶ </a></h4>
<p>@TODO</p>
<h2 id="ContentProvider内容提供者">ContentProvider内容提供者<a class="header-anchor" href="#ContentProvider内容提供者"> ¶ </a></h2>
<p>内容提供器（Content Provider）主要用于在不同的应用程序之间实现数据共享的功能，它提供了一套完整的机制，允许一个程序访问另一个程序中的数据，同时还能保证被访数据的安全性。目前，使用内容提供器是Android实现跨程序共享数据的标准方式。</p>
<h3 id="运行时权限">运行时权限<a class="header-anchor" href="#运行时权限"> ¶ </a></h3>
<h4 id="运行时权限机制">运行时权限机制<a class="header-anchor" href="#运行时权限机制"> ¶ </a></h4>
<p>Android现在将所有的权限归成了两类，一类是普通权限，一类是危险权限。准确地讲，其实还有第三类特殊权限，不过这种权限使用得很少，因此不在本书的讨论范围之内。普通权限指的是那些不会直接威胁到用户的安全和隐私的权限，对于这部分权限申请，系统会自动帮我们进行授权，而不需要用户再去手动操作了，比如在BroadcastTest项目中申请的两个权限就是普通权限。危险权限则表示那些可能会触及用户隐私或者对设备安全性造成影响的权限，如获取设备联系人信息、定位设备的地理位置等，对于这部分权限申请，必须要由用户手动点击授权才可以，否则程序就无法使用相应的功能。</p>
<p>查看Android系统中完整的权限列表：<a target="_blank" rel="noopener" href="https://developer.android.google.cn/reference/android/Manifest.permission.html">Manifest.permission  | Android Developers (google.cn)</a></p>
<h3 id="程序运行时申请权限">程序运行时申请权限<a class="header-anchor" href="#程序运行时申请权限"> ¶ </a></h3>
<h4 id="Android6-0之前">Android6.0之前<a class="header-anchor" href="#Android6-0之前"> ¶ </a></h4>
<p>Android6.0之前，不需要动态申请权限就可以使用危险权限</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Intent intent = <span class="keyword">new</span> Intent(Intent.ACTION_CALL);</span><br><span class="line">intent.setData(Uri.parse(<span class="string">&quot;tel:10086&quot;</span>));</span><br><span class="line">startActivity(intent);</span><br></pre></td></tr></table></figure>
<p>但需要在AndroidManifest.xml中申请静态权限</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.CALL_PHONE&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<h4 id="Android6-0以后，动态申请权限">Android6.0以后，动态申请权限<a class="header-anchor" href="#Android6-0以后，动态申请权限"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        Button makeCall = (Button) findViewById(R.id.make_call);</span><br><span class="line">        makeCall.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                <span class="keyword">if</span> (ContextCompat.checkSelfPermission(MainActivity.<span class="keyword">this</span>, Manifest.</span><br><span class="line">                    permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) &#123;</span><br><span class="line">                    ActivityCompat.requestPermissions(MainActivity.<span class="keyword">this</span>, <span class="keyword">new</span></span><br><span class="line">                        String[]&#123; Manifest.permission.CALL_PHONE &#125;, <span class="number">1</span>);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    call();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">call</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Intent intent = <span class="keyword">new</span> Intent(Intent.ACTION_CALL);</span><br><span class="line">            intent.setData(Uri.parse(<span class="string">&quot;tel:10086&quot;</span>));</span><br><span class="line">            startActivity(intent);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (SecurityException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onRequestPermissionsResult</span><span class="params">(<span class="keyword">int</span> requestCode, String[] permissions,</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="keyword">int</span>[] grantResults)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (requestCode) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">                <span class="keyword">if</span> (grantResults.length &gt; <span class="number">0</span> &amp;&amp; grantResults[<span class="number">0</span>] == PackageManager.</span><br><span class="line">                    PERMISSION_GRANTED) &#123;</span><br><span class="line">                    call();</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    Toast.makeText(<span class="keyword">this</span>, <span class="string">&quot;You denied the permission&quot;</span>, Toast.LENGTH_</span><br><span class="line">                        SHORT).show();</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol>
<li>
<p>先判断用户是不是已经给过授权</p>
<p>借助的是<code>ContextCompat.checkSelfPermission()</code>方法。</p>
<ul>
<li>checkSelfPermission() 方法：第一个参数是Context；第二个参数是具体的权限名</li>
<li>方法的返回值和<code>PackageManager.PERMISSION_GRANTED</code> 做比较，相等就说明用户已经授权，不等就表示用户没有授权</li>
</ul>
</li>
<li>
<p>如果已经授权，则调用相关执行逻辑</p>
</li>
<li>
<p>如果没有授权，则需要调用<code>ActivityCompat.requestPermissions()</code> 方法来向用户申请授权</p>
<ul>
<li><code>requestPermissions()</code> 方法
<ul>
<li>第一个参数要求是Activity的实例</li>
<li>第二个参数是一个String 数组，存放要申<br>
请的权限名</li>
<li>第三个参数是请求码（唯一值）这里传入了<code>1</code></li>
</ul>
</li>
</ul>
</li>
<li>
<p>最终都会回调到<code>onRequestPermissionsResult()</code> 方法中，而授权的结果则会封装在<code>rantResults</code> 参数当中。这里我们只需要判断一下最后的授权结果，如果用户同意的话就调用call() 方法来拨打电话，如果用户拒绝的话我们只能放弃操作，并且弹出一条失败提示。</p>
</li>
</ol>
<h3 id="访问其他程序中数据">访问其他程序中数据<a class="header-anchor" href="#访问其他程序中数据"> ¶ </a></h3>
<ul>
<li>内容提供器的用法：
<ul>
<li>使用现有的内容提供器来读取和操作相应程序中的数据</li>
<li>创建自己的内容提供器给我们程序的数据提供外部访问接口</li>
</ul>
</li>
</ul>
<h4 id="ContentResolver的基本用法">ContentResolver的基本用法<a class="header-anchor" href="#ContentResolver的基本用法"> ¶ </a></h4>
<p>对于每一个应用程序来说，如果想要访问内容提供器中共享的数据，就一定要借助<code>ContentResolver</code>类，可以通过<code>Context</code>中的<code>getContentResolver()</code> 方法获取到该类的实例。</p>
<p><code>ContentResolver</code>中提供了一系列的方法用于对数据进行<code>CRUD</code>操作，其中<code>insert()</code> 方法用于添加数据，<code>update()</code> 方法用于更新数据，<code>delete()</code> 方法用于删除数据，<code>query()</code> 方法用于查询数据。</p>
<ol>
<li>
<p>不同于<code>SQLiteDatabase</code>，<code>ContentResolver</code>中的增删改查方法都是不接收表名参数的，而是使用一个<code>Uri</code> 参数代替，这个参数被称为<code>内容URI</code></p>
<ul>
<li>
<p><code>内容URI</code>给内容提供器中的数据建立了唯一标识符</p>
<ul>
<li>
<p>主要由两部分组成：authority和path</p>
<ul>
<li>
<p>authority是用于对不同的应用程序做区分的，一般为了避免冲突，都会采用程序包名的方式来进行命名。比如某个程序的包名是com.example.app，那么该程序对应的authority就可以命名为com.example.app.provider。一般为<code>[PackageName].provider</code></p>
</li>
<li>
<p>path则是用于对同一应用程序中不同的表做区分的，通常都会添加到authority的后面。比如某个程序的数据库里存在两张表：table1和table2，这时就可以将path分别命名为/table1和/table2，然后把authority和path进行组合，内容URI就变成了com.example.app.provider/table1和com.example.app.provider/table2。不过，目前还很难辨认出这两个字符串就是两个内容URI，我们还需要在字符串的头部加上协议声明。</p>
</li>
<li>
<p>内容URI标准格式写法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">content:<span class="comment">//com.example.app.provider/table1</span></span><br><span class="line">content:<span class="comment">//com.example.app.provider/table2</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<p>得到内容URI字符串之后，我们还需要将它解析成<code>Uri 对象</code>才可以作为参数传入</p>
<p>需要调用<code>Uri.parse()</code>方法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Uri uri = Uri.parse(<span class="string">&quot;content://com.example.app.provider/table1&quot;</span>);</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>接下来可以使用<code>ContentResolver</code>来查询其他程序 数据库中表的数据了</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Cursor cursor = getContentResolver().query(</span><br><span class="line">    uri,</span><br><span class="line">    projection,</span><br><span class="line">    selection,</span><br><span class="line">    selectionArgs,</span><br><span class="line">    sortOrder);</span><br></pre></td></tr></table></figure>
<table>
<thead>
<tr>
<th style="text-align:center">ContentResolver.query()方法参数</th>
<th style="text-align:center">对应SQL部分</th>
<th style="text-align:center">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">uri</td>
<td style="text-align:center">from table_name</td>
<td style="text-align:center">指定查询某个应用程序下的某一张表</td>
</tr>
<tr>
<td style="text-align:center">projection</td>
<td style="text-align:center">select column1, column2</td>
<td style="text-align:center">指定查询的列名</td>
</tr>
<tr>
<td style="text-align:center">selection</td>
<td style="text-align:center">where column = value</td>
<td style="text-align:center">指定where 的约束条件</td>
</tr>
<tr>
<td style="text-align:center">selectionArgs</td>
<td style="text-align:center"></td>
<td style="text-align:center">为where 中的占位符提供具体的值</td>
</tr>
<tr>
<td style="text-align:center">sortOrder</td>
<td style="text-align:center">order by column1, column2</td>
<td style="text-align:center">指定查询结果的排序方式</td>
</tr>
</tbody>
</table>
</li>
</ol>
<ul>
<li>insert(uri, contentValues);</li>
<li>update(uri, contentValues, “column1 = ? and column2 = ?”, new String[] {“text”, “1”});</li>
<li>delete(uri, “column2 = ?”, new String[] { “1” });</li>
</ul>
<h4 id="读取系统联系人">读取系统联系人<a class="header-anchor" href="#读取系统联系人"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    ArrayAdapter&lt;String&gt; adapter;</span><br><span class="line">    List&lt;String&gt; contactsList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        ListView contactsView = (ListView) findViewById(R.id.contacts_view);</span><br><span class="line">        adapter = <span class="keyword">new</span> ArrayAdapter&lt;String&gt;(<span class="keyword">this</span>, android.R.layout. simple_list_</span><br><span class="line">            item_1, contactsList);</span><br><span class="line">        contactsView.setAdapter(adapter);</span><br><span class="line">        <span class="comment">// 判断权限</span></span><br><span class="line">        <span class="keyword">if</span> (ContextCompat.checkSelfPermission(<span class="keyword">this</span>, Manifest.permission.READ_</span><br><span class="line">            CONTACTS) != PackageManager.PERMISSION_GRANTED) &#123;</span><br><span class="line">            ActivityCompat.requestPermissions(<span class="keyword">this</span>, <span class="keyword">new</span> String[]&#123; Manifest.</span><br><span class="line">                permission.READ_CONTACTS &#125;, <span class="number">1</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            readContacts();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">readContacts</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        Cursor cursor = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 查询联系人数据</span></span><br><span class="line">            cursor = getContentResolver().query(ContactsContract.CommonDataKinds.</span><br><span class="line">                Phone.CONTENT_URI, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>);</span><br><span class="line">            <span class="keyword">if</span> (cursor != <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">while</span> (cursor.moveToNext()) &#123;</span><br><span class="line">                    <span class="comment">// 获取联系人姓名</span></span><br><span class="line">                    String displayName = cursor.getString(cursor.getColumnIndex</span><br><span class="line">                       (ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));</span><br><span class="line">                    <span class="comment">// 获取联系人手机号</span></span><br><span class="line">                    String number = cursor.getString(cursor.getColumnIndex</span><br><span class="line">                       (ContactsContract.CommonDataKinds.Phone.NUMBER));</span><br><span class="line">                    contactsList.add(displayName + <span class="string">&quot;\n&quot;</span> + number);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">// 通知刷新adapter</span></span><br><span class="line">                adapter.notifyDataSetChanged();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (cursor != <span class="keyword">null</span>) &#123;</span><br><span class="line">                cursor.close();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 接收权限申请返回结果</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onRequestPermissionsResult</span><span class="params">(<span class="keyword">int</span> requestCode, String[] permissions,</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="keyword">int</span>[] grantResults)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (requestCode) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">                <span class="keyword">if</span> (grantResults.length &gt; <span class="number">0</span> &amp;&amp; grantResults[<span class="number">0</span>] == PackageManager.</span><br><span class="line">                    PERMISSION_GRANTED) &#123;</span><br><span class="line">                    readContacts();</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    Toast.makeText(<span class="keyword">this</span>, <span class="string">&quot;You denied the permission&quot;</span>, Toast.LENGTH_</span><br><span class="line">                        SHORT).show();</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>同时还需在<code>AndroidManifest.xml</code>中添加权限</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.READ_CONTACTS&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<h3 id="创建自己的内容提供器">创建自己的内容提供器<a class="header-anchor" href="#创建自己的内容提供器"> ¶ </a></h3>
<h4 id="创建内容提供器的步骤">创建内容提供器的步骤<a class="header-anchor" href="#创建内容提供器的步骤"> ¶ </a></h4>
<ol>
<li>
<p>新建一个类去继承<code>ContentProvider</code> 的方式来创建一个自己的内容提供器。该类有6个抽象方法</p>
<ol>
<li>
<p>onCreate()：初始化内容提供器的时候调用。。通常会在这里完成对数据库的创建和升级等操作，返回true 表示内容提供器初始化成功，返回false则表示失败。</p>
</li>
<li>
<p>query()：从内容提供器中查询数据。使用uri 参数来确定查询哪张表，projection 参数用于确定查询哪些列，selection 和selectionArgs 参数用于约束查询哪些行，sortOrder 参数用于对结果进行排序，查询的结果存放在Cursor对象中返回。</p>
</li>
<li>
<p>insert()：向内容提供器中添加一条数据。使用uri 参数来确定要添加到的表，待添加的数据保存在values 参数中。添加完成后，返回一个用于表示这条新记录的URI。</p>
</li>
<li>
<p>update()：更新内容提供器中已有的数据。使用uri 参数来确定更新哪一张表中的数据，新数据保存在values 参数中，selection 和selectionArgs 参数用于约束更新哪些行，受影响的行数将作为返回值返回。</p>
</li>
<li>
<p>delete()：从内容提供器中删除数据。使用uri 参数来确定删除哪一张表中的数可以看到，几乎每一个方法都会带有Uri 这个参数，这个参数也正是调用ContentResolver的增删改查方法时传递过来的。而现在，我们需要对传入的Uri 参数进行解析，从中分析出调用方期望访问的表和数据。</p>
</li>
<li>
<p>getType()：根据传入的内容URI来返回相应的MIME类型。</p>
<p>一个内容URI所对应的MIME字符串主要由3部分组成</p>
<ul>
<li>必须以vnd 开头。</li>
<li>如果内容URI以路径结尾，则后接<code>android.cursor.dir/</code> ；如果内容URI以<code>id</code>结尾，则后接<code>android.cursor.item/</code> 。</li>
<li>最后接上<code>vnd.&lt;authority&gt;.&lt;path&gt;</code> 。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyProvider</span> <span class="keyword">extends</span> <span class="title">ContentProvider</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getType</span><span class="params">(Uri uri)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (uriMatcher.match(uri)) &#123;</span><br><span class="line">        <span class="keyword">case</span> TABLE1_DIR:</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;vnd.android.cursor.dir/vnd.com.example.app.provider.table1&quot;</span>;</span><br><span class="line">        <span class="keyword">case</span> TABLE1_ITEM:</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;vnd.android.cursor.item/vnd.com.example.app.provider.table1&quot;</span>;</span><br><span class="line">        <span class="keyword">case</span> TABLE2_DIR:</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;vnd.android.cursor.dir/vnd.com.example.app.provider.table2&quot;</span>;</span><br><span class="line">        <span class="keyword">case</span> TABLE2_ITEM:</span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;vnd.android.cursor.item/vnd.com.example.app.provider.table2&quot;</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
</li>
<li>
<p><code>URI</code>参数</p>
<ul>
<li>
<p>标准URI写法</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">content:<span class="comment">//[Package Name]/[Table Name]/[ID]</span></span><br></pre></td></tr></table></figure>
</li>
<li>
<p>通配符</p>
<ul>
<li><code>*</code>：表示匹配任意长度的任意字符
<ul>
<li>如匹配任意表：<code>content://[Package Name]/*</code></li>
</ul>
</li>
<li><code>#</code>：表示匹配任意长度的数字
<ul>
<li>如匹配table表任意一行内容：<code>content://[Package Name]/table/#</code></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>UriMatcher</code>类：</p>
<p>可以轻松地实现匹配内容URI的功能</p>
<ul>
<li>addURI() 方法： 接收3个参数，分别为<code>authority</code> 、<code>path</code> 和一个自定义代码传进去</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyProvider</span> <span class="keyword">extends</span> <span class="title">ContentProvider</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TABLE1_DIR = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TABLE1_ITEM = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TABLE2_DIR = <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TABLE2_ITEM = <span class="number">3</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> UriMatcher uriMatcher;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        uriMatcher = <span class="keyword">new</span> UriMatcher(UriMatcher.NO_MATCH);</span><br><span class="line">        uriMatcher.addURI(<span class="string">&quot;com.example.app.provider&quot;</span>, <span class="string">&quot;table1&quot;</span>, TABLE1_DIR);</span><br><span class="line">        uriMatcher.addURI(<span class="string">&quot;com.example.app.provider &quot;</span>, <span class="string">&quot;table1/#&quot;</span>, TABLE1_ITEM);</span><br><span class="line">        uriMatcher.addURI(<span class="string">&quot;com.example.app.provider &quot;</span>, <span class="string">&quot;table2&quot;</span>, TABLE2_DIR);</span><br><span class="line">        uriMatcher.addURI(<span class="string">&quot;com.example.app.provider &quot;</span>, <span class="string">&quot;table2/#&quot;</span>, TABLE2_ITEM);</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Cursor <span class="title">query</span><span class="params">(Uri uri, String[] projection, String selection, String[]</span></span></span><br><span class="line"><span class="params"><span class="function">        selectionArgs, String sortOrder)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (uriMatcher.match(uri)) &#123;</span><br><span class="line">        <span class="keyword">case</span> TABLE1_DIR:</span><br><span class="line">            <span class="comment">// 查询table1表中的所有数据</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> TABLE1_ITEM:</span><br><span class="line">            <span class="comment">// 查询table1表中的单条数据</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> TABLE2_DIR:</span><br><span class="line">            <span class="comment">// 查询table2表中的所有数据</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> TABLE2_ITEM:</span><br><span class="line">            <span class="comment">// 查询table2表中的单条数据</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="实现跨程序数据共享">实现跨程序数据共享<a class="header-anchor" href="#实现跨程序数据共享"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DatabaseProvider</span> <span class="keyword">extends</span> <span class="title">ContentProvider</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> BOOK_DIR = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> BOOK_ITEM = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> CATEGORY_DIR = <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> CATEGORY_ITEM = <span class="number">3</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String AUTHORITY = <span class="string">&quot;com.example.databasetest.provider&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> UriMatcher uriMatcher;</span><br><span class="line">    <span class="keyword">private</span> MyDatabaseHelper dbHelper;</span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        uriMatcher = <span class="keyword">new</span> UriMatcher(UriMatcher.NO_MATCH);</span><br><span class="line">        uriMatcher.addURI(AUTHORITY, <span class="string">&quot;book&quot;</span>, BOOK_DIR);</span><br><span class="line">        uriMatcher.addURI(AUTHORITY, <span class="string">&quot;book/#&quot;</span>, BOOK_ITEM);</span><br><span class="line">        uriMatcher.addURI(AUTHORITY, <span class="string">&quot;category&quot;</span>, CATEGORY_DIR);</span><br><span class="line">        uriMatcher.addURI(AUTHORITY, <span class="string">&quot;category/#&quot;</span>, CATEGORY_ITEM);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        dbHelper = <span class="keyword">new</span> MyDatabaseHelper(getContext(), <span class="string">&quot;BookStore.db&quot;</span>, <span class="keyword">null</span>, <span class="number">2</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Cursor <span class="title">query</span><span class="params">(Uri uri, String[] projection, String selection, String[]</span></span></span><br><span class="line"><span class="params"><span class="function">        selectionArgs, String sortOrder)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 查询数据</span></span><br><span class="line"></span><br><span class="line">        SQLiteDatabase db = dbHelper.getReadableDatabase();</span><br><span class="line">        Cursor cursor = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">switch</span> (uriMatcher.match(uri)) &#123;</span><br><span class="line">            <span class="keyword">case</span> BOOK_DIR:</span><br><span class="line">                cursor = db.query(<span class="string">&quot;Book&quot;</span>, projection, selection, selectionArgs, <span class="keyword">null</span>,</span><br><span class="line">                    <span class="keyword">null</span>, sortOrder);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> BOOK_ITEM:</span><br><span class="line">                String bookId = uri.getPathSegments().get(<span class="number">1</span>);</span><br><span class="line">                cursor = db.query(<span class="string">&quot;Book&quot;</span>, projection, <span class="string">&quot;id = ?&quot;</span>, <span class="keyword">new</span> String[] &#123; bookId &#125;,</span><br><span class="line">                    <span class="keyword">null</span>, <span class="keyword">null</span>, sortOrder);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_DIR:</span><br><span class="line">                cursor = db.query(<span class="string">&quot;Category&quot;</span>, projection, selection, selectionArgs,</span><br><span class="line">                    <span class="keyword">null</span>, <span class="keyword">null</span>, sortOrder);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_ITEM:</span><br><span class="line">                String categoryId = uri.getPathSegments().get(<span class="number">1</span>);</span><br><span class="line">                cursor = db.query(<span class="string">&quot;Category&quot;</span>, projection, <span class="string">&quot;id = ?&quot;</span>, <span class="keyword">new</span> String[]</span><br><span class="line">                    &#123; categoryId &#125;, <span class="keyword">null</span>, <span class="keyword">null</span>, sortOrder);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> cursor;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Uri <span class="title">insert</span><span class="params">(Uri uri, ContentValues values)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 添加数据</span></span><br><span class="line">        SQLiteDatabase db = dbHelper.getWritableDatabase();</span><br><span class="line">        Uri uriReturn = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">switch</span> (uriMatcher.match(uri)) &#123;</span><br><span class="line">            <span class="keyword">case</span> BOOK_DIR:</span><br><span class="line">            <span class="keyword">case</span> BOOK_ITEM:</span><br><span class="line">                <span class="keyword">long</span> newBookId = db.insert(<span class="string">&quot;Book&quot;</span>, <span class="keyword">null</span>, values);</span><br><span class="line">                uriReturn = Uri.parse(<span class="string">&quot;content://&quot;</span> + AUTHORITY + <span class="string">&quot;/book/&quot;</span> +</span><br><span class="line">                   newBookId);</span><br><span class="line">                <span class="comment">/**</span></span><br><span class="line"><span class="comment">                 * Uri uri = Uri.parse(&quot;content://org.providers.prods/word&quot;);</span></span><br><span class="line"><span class="comment">                 * Uri resultUri = ContentUris.withAppendedId(uri,5);</span></span><br><span class="line"><span class="comment">                 * // 返回resultUri为：content://org.providers.prods/word/5</span></span><br><span class="line"><span class="comment">                 * Long id = ContentUris.parseId(resultUri); </span></span><br><span class="line"><span class="comment">                 * // 返回5</span></span><br><span class="line"><span class="comment">                 */</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_DIR:</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_ITEM:</span><br><span class="line">                <span class="keyword">long</span> newCategoryId = db.insert(<span class="string">&quot;Category&quot;</span>, <span class="keyword">null</span>, values);</span><br><span class="line">                uriReturn = Uri.parse(<span class="string">&quot;content://&quot;</span> + AUTHORITY + <span class="string">&quot;/category/&quot;</span> +</span><br><span class="line">                    newCategoryId);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line"></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> uriReturn;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">update</span><span class="params">(Uri uri, ContentValues values, String selection, String[]</span></span></span><br><span class="line"><span class="params"><span class="function">        selectionArgs)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 更新数据</span></span><br><span class="line">        SQLiteDatabase db = dbHelper.getWritableDatabase();</span><br><span class="line">        <span class="keyword">int</span> updatedRows = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">switch</span> (uriMatcher.match(uri)) &#123;</span><br><span class="line">            <span class="keyword">case</span> BOOK_DIR:</span><br><span class="line">                updatedRows = db.update(<span class="string">&quot;Book&quot;</span>, values, selection, selectionArgs);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> BOOK_ITEM:</span><br><span class="line">                String bookId = uri.getPathSegments().get(<span class="number">1</span>);</span><br><span class="line">                updatedRows = db.update(<span class="string">&quot;Book&quot;</span>, values, <span class="string">&quot;id = ?&quot;</span>, <span class="keyword">new</span> String[]</span><br><span class="line">                    &#123; bookId &#125;);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_DIR:</span><br><span class="line">                updatedRows = db.update(<span class="string">&quot;Category&quot;</span>, values, selection,</span><br><span class="line">                    selectionArgs);</span><br><span class="line"></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_ITEM:</span><br><span class="line">                String categoryId = uri.getPathSegments().get(<span class="number">1</span>);</span><br><span class="line">                updatedRows = db.update(<span class="string">&quot;Category&quot;</span>, values, <span class="string">&quot;id = ?&quot;</span>, <span class="keyword">new</span> String[]</span><br><span class="line">                    &#123; categoryId &#125;);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> updatedRows;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">delete</span><span class="params">(Uri uri, String selection, String[] selectionArgs)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 删除数据</span></span><br><span class="line">        SQLiteDatabase db = dbHelper.getWritableDatabase();</span><br><span class="line">        <span class="keyword">int</span> deletedRows = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">switch</span> (uriMatcher.match(uri)) &#123;</span><br><span class="line">            <span class="keyword">case</span> BOOK_DIR:</span><br><span class="line">                deletedRows = db.delete(<span class="string">&quot;Book&quot;</span>, selection, selectionArgs);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> BOOK_ITEM:</span><br><span class="line">                String bookId = uri.getPathSegments().get(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line">                deletedRows = db.delete(<span class="string">&quot;Book&quot;</span>, <span class="string">&quot;id = ?&quot;</span>, <span class="keyword">new</span> String[] &#123; bookId &#125;);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_DIR:</span><br><span class="line">                deletedRows = db.delete(<span class="string">&quot;Category&quot;</span>, selection, selectionArgs);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_ITEM:</span><br><span class="line">                String categoryId = uri.getPathSegments().get(<span class="number">1</span>);</span><br><span class="line">                deletedRows = db.delete(<span class="string">&quot;Category&quot;</span>, <span class="string">&quot;id = ?&quot;</span>, <span class="keyword">new</span> String[]</span><br><span class="line">                    &#123; categoryId &#125;);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> deletedRows;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getType</span><span class="params">(Uri uri)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (uriMatcher.match(uri)) &#123;</span><br><span class="line">            <span class="keyword">case</span> BOOK_DIR:</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;vnd.android.cursor.dir/vnd.com.example.databasetest.provider.book&quot;</span>;</span><br><span class="line">            <span class="keyword">case</span> BOOK_ITEM:</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;vnd.android.cursor.item/vnd.com.example.databasetest.provider.book&quot;</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_DIR:</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;vnd.android.cursor.dir/vnd.com.example.databasetest.provider.category&quot;</span>;</span><br><span class="line">            <span class="keyword">case</span> CATEGORY_ITEM:</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;vnd.android.cursor.item/vnd.com.example.databasetest.provider.category&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>其中还需要在<code>AndroidManifest.xml</code>中注册<code>provider</code></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">provider</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:name</span>=<span class="string">&quot;.DatabaseProvider&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:authorities</span>=<span class="string">&quot;com.example.databasetest.provider&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:enabled</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:exported</span>=<span class="string">&quot;true&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">provider</span>&gt;</span></span><br></pre></td></tr></table></figure>
<ul>
<li><code>android:name</code> 属性指定了<code>DatabaseProvider</code>的类名</li>
<li><code>android:authorities</code> 属性指定了<code>DatabaseProvider</code>的<code>authority</code></li>
<li><code>enabled</code> 和<code>exported</code> 属性则是根据我们刚才勾选的状态自动生成的，这里表示允许<code>DatabaseProvider</code>被其他应用程序进行访问；Enabled 属性表示是否启用</li>
</ul>
<p>另写一程序来调用该数据库</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String newId;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        Button addData = (Button) findViewById(R.id.add_data);</span><br><span class="line">        addData.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 添加数据</span></span><br><span class="line">                Uri uri = Uri.parse(<span class="string">&quot;content://com.example.databasetest.provider/book&quot;</span>);</span><br><span class="line">                ContentValues values = <span class="keyword">new</span> ContentValues();</span><br><span class="line">                values.put(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;A Clash of Kings&quot;</span>);</span><br><span class="line">                values.put(<span class="string">&quot;author&quot;</span>, <span class="string">&quot;George Martin&quot;</span>);</span><br><span class="line">                values.put(<span class="string">&quot;pages&quot;</span>, <span class="number">1040</span>);</span><br><span class="line">                values.put(<span class="string">&quot;price&quot;</span>, <span class="number">22.85</span>);</span><br><span class="line">                Uri newUri = getContentResolver().insert(uri, values);</span><br><span class="line"></span><br><span class="line">                newId = newUri.getPathSegments().get(<span class="number">1</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        Button queryData = (Button) findViewById(R.id.query_data);</span><br><span class="line">        queryData.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 查询数据</span></span><br><span class="line">                Uri uri = Uri.parse(<span class="string">&quot;content://com.example.databasetest. provider/book&quot;</span>);</span><br><span class="line">                Cursor cursor = getContentResolver().query(uri, <span class="keyword">null</span>, <span class="keyword">null</span>, <span class="keyword">null</span>,</span><br><span class="line">                    <span class="keyword">null</span>);</span><br><span class="line">                <span class="keyword">if</span> (cursor != <span class="keyword">null</span>) &#123;</span><br><span class="line">                    <span class="keyword">while</span> (cursor.moveToNext()) &#123;</span><br><span class="line">                        String name = cursor.getString(cursor. getColumnIndex</span><br><span class="line">                            (<span class="string">&quot;name&quot;</span>));</span><br><span class="line">                        String author = cursor.getString(cursor. getColumnIndex</span><br><span class="line">                            (<span class="string">&quot;author&quot;</span>));</span><br><span class="line">                        <span class="keyword">int</span> pages = cursor.getInt(cursor.getColumnIndex (<span class="string">&quot;pages&quot;</span>));</span><br><span class="line">                        <span class="keyword">double</span> price = cursor.getDouble(cursor. getColumnIndex</span><br><span class="line">                            (<span class="string">&quot;price&quot;</span>));</span><br><span class="line">                        Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;book name is &quot;</span> + name);</span><br><span class="line">                        Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;book author is &quot;</span> + author);</span><br><span class="line"></span><br><span class="line">                        Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;book pages is &quot;</span> + pages);</span><br><span class="line">                        Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;book price is &quot;</span> + price);</span><br><span class="line">                    &#125;</span><br><span class="line">                    cursor.close();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        Button updateData = (Button) findViewById(R.id.update_data);</span><br><span class="line">        updateData.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 更新数据</span></span><br><span class="line">                Uri uri = Uri.parse(<span class="string">&quot;content://com.example.databasetest. provider/book/&quot;</span> + newId);</span><br><span class="line">                ContentValues values = <span class="keyword">new</span> ContentValues();</span><br><span class="line">                values.put(<span class="string">&quot;name&quot;</span>, <span class="string">&quot;A Storm of Swords&quot;</span>);</span><br><span class="line">                values.put(<span class="string">&quot;pages&quot;</span>, <span class="number">1216</span>);</span><br><span class="line">                values.put(<span class="string">&quot;price&quot;</span>, <span class="number">24.05</span>);</span><br><span class="line">                getContentResolver().update(uri, values, <span class="keyword">null</span>, <span class="keyword">null</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        Button deleteData = (Button) findViewById(R.id.delete_data);</span><br><span class="line">        deleteData.setOnClickListener(<span class="keyword">new</span> View.OnClickListener() &#123;</span><br><span class="line"></span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 删除数据</span></span><br><span class="line">                Uri uri = Uri.parse(<span class="string">&quot;content://com.example.databasetest. provider/book/&quot;</span> + newId);</span><br><span class="line">                getContentResolver().delete(uri, <span class="keyword">null</span>, <span class="keyword">null</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="使用网络技术">使用网络技术<a class="header-anchor" href="#使用网络技术"> ¶ </a></h2>
<h3 id="使用Http访问网络">使用Http访问网络<a class="header-anchor" href="#使用Http访问网络"> ¶ </a></h3>
<h4 id="使用HttpURLConnection">使用HttpURLConnection<a class="header-anchor" href="#使用HttpURLConnection"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// new一个Url对象</span></span><br><span class="line">URL url = <span class="keyword">new</span> URL(<span class="string">&quot;http://www.baidu.com&quot;</span>);</span><br><span class="line"><span class="comment">// new HttpURLConnection 新建连接</span></span><br><span class="line">HttpURLConnection connection = (HttpURLConnection) url.openConnection();</span><br><span class="line"><span class="comment">// 可设置请求方式 GET/POST</span></span><br><span class="line">connection.setRequestMethod(<span class="string">&quot;GET&quot;</span>);</span><br><span class="line"><span class="comment">// 设置连接超时毫秒数</span></span><br><span class="line">connection.setConnectTimeout(<span class="number">8000</span>);</span><br><span class="line"><span class="comment">// 设置读取超时毫秒数</span></span><br><span class="line">connection.setReadTimeout(<span class="number">8000</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果为POST，获取输出流</span></span><br><span class="line">OutputStream os = connection.getOutputStream();</span><br><span class="line"><span class="comment">// 传入post参数</span></span><br><span class="line">os.write(<span class="string">&quot;username=张三&amp;age=20&quot;</span>.getBytes());</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获得输入流</span></span><br><span class="line">InputStream in = connection.getInputStream();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 进行字节流读取相关操作</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 关闭流</span></span><br><span class="line">in.close();</span><br><span class="line">os.close();</span><br><span class="line"><span class="comment">// 关闭连接</span></span><br><span class="line">connection.disconnect();</span><br></pre></td></tr></table></figure>
<h4 id="使用OkHttp">使用OkHttp<a class="header-anchor" href="#使用OkHttp"> ¶ </a></h4>
<h5 id="导入依赖">导入依赖<a class="header-anchor" href="#导入依赖"> ¶ </a></h5>
<p>编辑<code>app/build.gradle</code>，添加依赖</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">dependencies &#123;</span><br><span class="line">    compile <span class="string">&#x27;com.squareup.okhttp3:okhttp:3.10.0&#x27;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h5 id="使用-2">使用<a class="header-anchor" href="#使用-2"> ¶ </a></h5>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建一个OkHttpClient的实例</span></span><br><span class="line">OkHttpClient client = <span class="keyword">new</span> OkHttpClient();</span><br><span class="line"><span class="comment">// 创建一个(空)Request 对象：</span></span><br><span class="line">Request request = <span class="keyword">new</span> Request.Builder().build();</span><br><span class="line"><span class="comment">// 或者在Builder中设置url</span></span><br><span class="line">Request request = <span class="keyword">new</span> Request.Builder()</span><br><span class="line">        .url(<span class="string">&quot;http://www.baidu.com&quot;</span>)</span><br><span class="line">        .build();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 之后调用OkHttpClient的newCall() 方法来创建一个Call 对象，并调用它的execute() 方法来发送请求并获取服务器返回的数据</span></span><br><span class="line">Response response = client.newCall(request).execute();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 得到Response返回的具体内容</span></span><br><span class="line">String responseData = response.body().string();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果为POST 我们需要先构建出一个Request Body对象来存放待提交的参数</span></span><br><span class="line">RequestBody requestBody = <span class="keyword">new</span> FormBody.Builder()</span><br><span class="line">        .add(<span class="string">&quot;username&quot;</span>, <span class="string">&quot;admin&quot;</span>)</span><br><span class="line">        .add(<span class="string">&quot;password&quot;</span>, <span class="string">&quot;123456&quot;</span>)</span><br><span class="line">        .build();</span><br><span class="line"><span class="comment">// Request.Builder中调用一下post() 方法，并将RequestBody 对象传入</span></span><br><span class="line">Request request = <span class="keyword">new</span> Request.Builder()</span><br><span class="line">        .url(<span class="string">&quot;http://www.baidu.com&quot;</span>)</span><br><span class="line">        .post(requestBody)</span><br><span class="line">        .build();</span><br><span class="line"><span class="comment">// 调用execute() 方法来发送请求并获取服务器返回的数据即可。</span></span><br></pre></td></tr></table></figure>
<h6 id="get同步请求">get同步请求<a class="header-anchor" href="#get同步请求"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建OkHttpClient对象</span></span><br><span class="line">OkHttpClient client = <span class="keyword">new</span> OkHttpClient.Builder()</span><br><span class="line">    .cache() <span class="comment">// 设置缓存目录（有默认）</span></span><br><span class="line">    .connectTimeout()	<span class="comment">// 设置连接超时（有默认）</span></span><br><span class="line">    .cookieJar()	<span class="comment">// cookie的读取，保存（需自己实现）</span></span><br><span class="line">    .build();</span><br><span class="line"><span class="comment">// 创建Request对象</span></span><br><span class="line">Request request = <span class="keyword">new</span> Request.Builder()</span><br><span class="line">    .url(address)</span><br><span class="line">    .build();</span><br><span class="line"><span class="comment">// 发送请求，获取响应</span></span><br><span class="line">Call call = client.newCall(request);</span><br><span class="line"><span class="comment">// 发送同步请求，需手动创建子线程</span></span><br><span class="line"><span class="keyword">new</span> Thread()&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span>&#123;</span><br><span class="line">        Response response = call.execute();<span class="comment">//等待服务端进行响应（等待过程中会阻塞）</span></span><br><span class="line">        <span class="comment">// 判断响应状态是否正常</span></span><br><span class="line">        <span class="keyword">if</span>(response.isSuccessful())&#123;</span><br><span class="line">            <span class="comment">// 获取服务端响应的内容（文本）</span></span><br><span class="line">            String str = response.body().string();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h6 id="get异步请求">get异步请求<a class="header-anchor" href="#get异步请求"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//发送异步方式的get请求</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">getAsync</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="comment">//2.创建请求对象</span></span><br><span class="line">    Request request = <span class="keyword">new</span> Request.Builder()</span><br><span class="line">            .url(Constant.BASE_URL +</span><br><span class="line">                    <span class="string">&quot;LoginServlet?username=张三&amp;password=123&quot;</span>)</span><br><span class="line">            .build();</span><br><span class="line">    <span class="comment">//3.发送请求，获取响应</span></span><br><span class="line">    Call call = okHttpClient.newCall(request);</span><br><span class="line">    <span class="comment">//异步请求，不需要手动创建子线程</span></span><br><span class="line">    call.enqueue(<span class="keyword">new</span> Callback()&#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onFailure</span><span class="params">(Call call, IOException e)</span> </span>&#123;</span><br><span class="line">            <span class="comment">//请求失败时执行</span></span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span><span class="params">(Call call, Response response)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">            <span class="comment">//请求成功时执行</span></span><br><span class="line">            Log.e(<span class="string">&quot;onResponse&quot;</span>,Thread.currentThread().getName());</span><br><span class="line">            Log.e(<span class="string">&quot;异步get请求的结果&quot;</span>,response.body().string());</span><br><span class="line">            <span class="comment">//执行在子线程中，不能直接修改用户界面</span></span><br><span class="line">            <span class="comment">//可以借助Handler实现</span></span><br><span class="line"></span><br><span class="line">            <span class="comment">//在实现文件下载功能时，如何获取网络文件的数据</span></span><br><span class="line"><span class="comment">//                InputStream is = response.body().byteStream();</span></span><br><span class="line"><span class="comment">//                FileOutputStream fos = new FileOutputStream(</span></span><br><span class="line"><span class="comment">//                        getExternalFilesDir(null).getAbsolutePath() + &quot;/a.jpg&quot;);</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    Log.e(<span class="string">&quot;okhttp&quot;</span>,<span class="string">&quot;异步请求已发送&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h6 id="异步post：发送文本">异步post：发送文本<a class="header-anchor" href="#异步post：发送文本"> ¶ </a></h6>
<p><a target="_blank" rel="noopener" href="https://www.w3school.com.cn/media/media_mimeref.asp">MIME 参考手册 (w3school.com.cn)</a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">//异步方式的post请求，发送文本数据</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">postAsync</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="comment">//2.创建请求体对象</span></span><br><span class="line">    RequestBody requestBody = RequestBody.create(</span><br><span class="line">            MediaType.parse(<span class="string">&quot;text/plain;charset=utf-8&quot;</span>),	<span class="comment">// 根据上传类型选择相应MIME</span></span><br><span class="line">            <span class="string">&quot;username=张三&amp;password=123&quot;</span>);</span><br><span class="line">    <span class="comment">//3.创建请求对象</span></span><br><span class="line">    Request request = <span class="keyword">new</span> Request.Builder()</span><br><span class="line">            .url(Constant.BASE_URL + <span class="string">&quot;LoginServlet&quot;</span>)</span><br><span class="line">            .post(requestBody)<span class="comment">//设置请求方式为POST</span></span><br><span class="line">            .build();</span><br><span class="line">    <span class="comment">//4.发送请求，获取响应</span></span><br><span class="line">    Call call = okHttpClient.newCall(request);</span><br><span class="line">    <span class="comment">//异步请求，不需要手动创建子线程</span></span><br><span class="line">    call.enqueue(<span class="keyword">new</span> Callback()&#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onFailure</span><span class="params">(Call call, IOException e)</span> </span>&#123;</span><br><span class="line">            <span class="comment">//请求失败时执行</span></span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span><span class="params">(Call call, Response response)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">            <span class="comment">//请求成功时执行</span></span><br><span class="line">            Log.e(<span class="string">&quot;onResponse&quot;</span>,Thread.currentThread().getName());</span><br><span class="line">            Log.e(<span class="string">&quot;异步get请求的结果&quot;</span>,response.body().string());</span><br><span class="line">            <span class="comment">//执行在子线程中，不能直接修改用户界面</span></span><br><span class="line">            <span class="comment">//可以借助Handler实现</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h6 id="异步post：发送表单">异步post：发送表单<a class="header-anchor" href="#异步post：发送表单"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//2.创建请求体对象</span></span><br><span class="line">FormBody formBody = <span class="keyword">new</span> FormBody.Builder()</span><br><span class="line">        .add(<span class="string">&quot;username&quot;</span>,<span class="string">&quot;张三&quot;</span>)</span><br><span class="line">        .add(<span class="string">&quot;password&quot;</span>,<span class="string">&quot;123&quot;</span>)</span><br><span class="line">        .build();</span><br><span class="line"></span><br><span class="line"><span class="comment">//3.创建请求对象</span></span><br><span class="line">Request request = <span class="keyword">new</span> Request.Builder()</span><br><span class="line">        .url(Constant.BASE_URL + <span class="string">&quot;LoginServlet&quot;</span>)</span><br><span class="line">        .post(formBody)<span class="comment">//设置请求方式为POST</span></span><br><span class="line">        .build();</span><br></pre></td></tr></table></figure>
<h6 id="post本地选择文件上传">post本地选择文件上传<a class="header-anchor" href="#post本地选择文件上传"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//文件上传</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">uploadFile</span><span class="params">()</span></span>&#123;</span><br><span class="line">    Intent intent = <span class="keyword">new</span> Intent();</span><br><span class="line">    intent.setAction(Intent.ACTION_PICK);</span><br><span class="line">    intent.setType(<span class="string">&quot;image/*&quot;</span>);</span><br><span class="line">    startActivityForResult(intent, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onActivityResult</span><span class="params">(<span class="keyword">int</span> requestCode, <span class="keyword">int</span> resultCode, <span class="meta">@Nullable</span> Intent data)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">super</span>.onActivityResult(requestCode, resultCode, data);</span><br><span class="line">    <span class="keyword">if</span> (requestCode == <span class="number">1</span> &amp;&amp; resultCode == RESULT_OK)&#123;</span><br><span class="line">        ContentResolver contentResolver = getContentResolver();</span><br><span class="line">        Cursor cursor = contentResolver.query(data.getData(),</span><br><span class="line">                <span class="keyword">null</span>,<span class="keyword">null</span>,<span class="keyword">null</span>,<span class="keyword">null</span>);</span><br><span class="line">        <span class="keyword">if</span> (cursor.moveToFirst())&#123;</span><br><span class="line">            String imagePath = cursor.getString(cursor.getColumnIndex(<span class="string">&quot;_data&quot;</span>));</span><br><span class="line">            <span class="comment">//创建请求体对象</span></span><br><span class="line">            File file = <span class="keyword">new</span> File(imagePath);</span><br><span class="line">            RequestBody requestBody = RequestBody.create(</span><br><span class="line">                    MediaType.parse(<span class="string">&quot;application/octet-stream&quot;</span>),</span><br><span class="line">                    file);</span><br><span class="line">            <span class="comment">//创建请求对象</span></span><br><span class="line">            Request request = <span class="keyword">new</span> Request.Builder()</span><br><span class="line">                    .url(Constant.BASE_URL + <span class="string">&quot;UploadServlet&quot;</span>)</span><br><span class="line">                    .post(requestBody)</span><br><span class="line">                    .build();</span><br><span class="line">            Call call = okHttpClient.newCall(request);</span><br><span class="line">            call.enqueue(<span class="keyword">new</span> Callback() &#123;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onFailure</span><span class="params">(Call call, IOException e)</span> </span>&#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span><span class="params">(Call call, Response response)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">                    Log.e(<span class="string">&quot;上传文件的结果&quot;</span>,response.body().string());</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h6 id="post下载远端">post下载远端<a class="header-anchor" href="#post下载远端"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span><span class="params">(Call call, Response r)</span> <span class="keyword">throws</span> IOException</span>&#123;</span><br><span class="line">    InputStream is = response.body().byteStream();</span><br><span class="line">    File file = <span class="keyword">new</span> File(Environment.getExternalStorageDirectory(), </span><br><span class="line">                        <span class="string">&quot;test.txt&quot;</span>);</span><br><span class="line">    FileOutputStream fos = <span class="keyword">new</span> FileOutputStream(file);</span><br><span class="line">    <span class="keyword">int</span> len = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">byte</span>[] buf = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">128</span>];</span><br><span class="line">    <span class="keyword">while</span> ((len = is.read(buf)) != -<span class="number">1</span>)&#123;</span><br><span class="line">        fos.write(buf, <span class="number">0</span>, len);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="解析XML格式数据">解析XML格式数据<a class="header-anchor" href="#解析XML格式数据"> ¶ </a></h3>
<h4 id="Pull解析方式">Pull解析方式<a class="header-anchor" href="#Pull解析方式"> ¶ </a></h4>
<p>解析的xml</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">apps</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">app</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span>&gt;</span>1<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>Google Maps<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">app</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">app</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span>&gt;</span>2<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>Chrome<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">app</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">app</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span>&gt;</span>3<span class="tag">&lt;/<span class="name">id</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">name</span>&gt;</span>Google Play<span class="tag">&lt;/<span class="name">name</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.3<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">app</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">apps</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>java代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parseXMLWithPull</span><span class="params">(String xmlData)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();</span><br><span class="line">        <span class="comment">// 创建xmlPull解析器</span></span><br><span class="line">        <span class="comment">// XmlPullParser parser = Xml.newPullParser();</span></span><br><span class="line">        XmlPullParser xmlPullParser = factory.newPullParser();</span><br><span class="line">        <span class="comment">// 初始化解析器</span></span><br><span class="line">        xmlPullParser.setInput(<span class="keyword">new</span> StringReader(xmlData));</span><br><span class="line">        <span class="comment">// 当前读取的事件类型</span></span><br><span class="line">        <span class="keyword">int</span> eventType = xmlPullParser.getEventType();</span><br><span class="line">        String id = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        String name = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        String version = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        <span class="comment">// 如果没有读取到文档的末尾</span></span><br><span class="line">        <span class="keyword">while</span> (eventType != XmlPullParser.END_DOCUMENT) &#123;</span><br><span class="line">            <span class="comment">// 获得当前节点的名称</span></span><br><span class="line">            String nodeName = xmlPullParser.getName();</span><br><span class="line">            <span class="keyword">switch</span> (eventType) &#123;</span><br><span class="line">                <span class="comment">// 开始标签</span></span><br><span class="line">                <span class="keyword">case</span> XmlPullParser.START_TAG: &#123;</span><br><span class="line">                    <span class="keyword">if</span> (<span class="string">&quot;id&quot;</span>.equals(nodeName)) &#123;</span><br><span class="line">                        id = xmlPullParser.nextText();</span><br><span class="line">                    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">&quot;name&quot;</span>.equals(nodeName)) &#123;</span><br><span class="line">                        name = xmlPullParser.nextText();</span><br><span class="line">                    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">&quot;version&quot;</span>.equals(nodeName)) &#123;</span><br><span class="line">                        version = xmlPullParser.nextText();</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">// 结束标签</span></span><br><span class="line">                <span class="keyword">case</span> XmlPullParser.END_TAG: &#123;</span><br><span class="line">                    <span class="keyword">if</span> (<span class="string">&quot;app&quot;</span>.equals(nodeName)) &#123;</span><br><span class="line">                        Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;id is &quot;</span> + id);</span><br><span class="line">                        Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;name is &quot;</span> + name);</span><br><span class="line">                        Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;version is &quot;</span> + version);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">default</span>:</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            eventType = xmlPullParser.next();</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ol>
<li>首先要获取到一个XmlPullParserFactory 的实例</li>
<li>借助这个实例得到XmlPullParser 对象</li>
<li>然后调用XmlPullParser 的setInput() 方法将服务器返回的XML数据设置进去就可以开始解析了。</li>
<li>解析的过程也非常简单，通过getEventType() 可以得到当前的解析事件</li>
<li>然后在一个while循环中不断地进行解析如果当前的解析事件不等于XmlPullParser.END_DOCUMENT，说明解析工作还没完成,调用next() 方法后可以获取下一个解析事件。</li>
<li>在while 循环中，我们通过getName() 方法得到当前节点的名字，如果发现节点名等于id、name或version，就调用nextText() 方法来获取节点内具体的内容，每当解析完一个app节点后就将获取到的内容打印出来。</li>
</ol>
<h4 id="SAX解析方式">SAX解析方式<a class="header-anchor" href="#SAX解析方式"> ¶ </a></h4>
<p>模板</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyHandler</span> <span class="keyword">extends</span> <span class="title">DefaultHandler</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">startDocument</span><span class="params">()</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        <span class="comment">// startDocument() 方法会在开始XML解析的时候调用</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">startElement</span><span class="params">(String uri, String localName, String qName, Attributes</span></span></span><br><span class="line"><span class="params"><span class="function">        attributes)</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        <span class="comment">// startElement() 方法会在开始解析某个节点的时候调用</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">characters</span><span class="params">(<span class="keyword">char</span>[] ch, <span class="keyword">int</span> start, <span class="keyword">int</span> length)</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        <span class="comment">// characters() 方法会在获取节点中内容的时候调用</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">endElement</span><span class="params">(String uri, String localName, String qName)</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        <span class="comment">// endElement() 方法会在完成解析某个节点的时候调用</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">endDocument</span><span class="params">()</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        <span class="comment">// endDocument() 方法会在完成整个XML解析的时候调用</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>解析上述XML</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ContentHandler</span> <span class="keyword">extends</span> <span class="title">DefaultHandler</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String nodeName;</span><br><span class="line">    <span class="keyword">private</span> StringBuilder id;</span><br><span class="line">    <span class="keyword">private</span> StringBuilder name;</span><br><span class="line">    <span class="keyword">private</span> StringBuilder version;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">startDocument</span><span class="params">()</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        id = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">        name = <span class="keyword">new</span> StringBuilder();</span><br><span class="line"></span><br><span class="line">        version = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">startElement</span><span class="params">(String uri, String localName, String qName, Attributes</span></span></span><br><span class="line"><span class="params"><span class="function">        attributes)</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        <span class="comment">// 记录当前节点名</span></span><br><span class="line">        nodeName = localName;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">characters</span><span class="params">(<span class="keyword">char</span>[] ch, <span class="keyword">int</span> start, <span class="keyword">int</span> length)</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        <span class="comment">// 根据当前的节点名判断将内容添加到哪一个StringBuilder对象中</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="string">&quot;id&quot;</span>.equals(nodeName)) &#123;</span><br><span class="line">            id.append(ch, start, length);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">&quot;name&quot;</span>.equals(nodeName)) &#123;</span><br><span class="line">            name.append(ch, start, length);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">&quot;version&quot;</span>.equals(nodeName)) &#123;</span><br><span class="line">            version.append(ch, start, length);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">endElement</span><span class="params">(String uri, String localName, String qName)</span> <span class="keyword">throws</span></span></span><br><span class="line"><span class="function">        SAXException </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="string">&quot;app&quot;</span>.equals(localName)) &#123;</span><br><span class="line">            Log.d(<span class="string">&quot;ContentHandler&quot;</span>, <span class="string">&quot;id is &quot;</span> + id.toString().trim());</span><br><span class="line">            Log.d(<span class="string">&quot;ContentHandler&quot;</span>, <span class="string">&quot;name is &quot;</span> + name.toString().trim());</span><br><span class="line">            Log.d(<span class="string">&quot;ContentHandler&quot;</span>, <span class="string">&quot;version is &quot;</span> + version.toString().trim());</span><br><span class="line">            <span class="comment">// 最后要将StringBuilder清空掉</span></span><br><span class="line">            id.setLength(<span class="number">0</span>);</span><br><span class="line">            name.setLength(<span class="number">0</span>);</span><br><span class="line">            version.setLength(<span class="number">0</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">endDocument</span><span class="params">()</span> <span class="keyword">throws</span> SAXException </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.endDocument();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>调用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parseXMLWithSAX</span><span class="params">(String xmlData)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        SAXParserFactory factory = SAXParserFactory.newInstance();</span><br><span class="line">        XMLReader xmlReader = factory.newSAXParser().getXMLReader();</span><br><span class="line">        ContentHandler handler = <span class="keyword">new</span> ContentHandler();</span><br><span class="line">        <span class="comment">// 将ContentHandler的实例设置到XMLReader中</span></span><br><span class="line">        xmlReader.setContentHandler(handler);</span><br><span class="line">        <span class="comment">// 开始执行解析</span></span><br><span class="line">        xmlReader.parse(<span class="keyword">new</span> InputSource(<span class="keyword">new</span> StringReader(xmlData)));</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="解析JSON格式数据">解析JSON格式数据<a class="header-anchor" href="#解析JSON格式数据"> ¶ </a></h3>
<p>测试Json数据</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[&#123;<span class="attr">&quot;id&quot;</span>:<span class="string">&quot;5&quot;</span>,<span class="attr">&quot;version&quot;</span>:<span class="string">&quot;5.5&quot;</span>,<span class="attr">&quot;name&quot;</span>:<span class="string">&quot;Clash of Clans&quot;</span>&#125;,</span><br><span class="line">&#123;<span class="attr">&quot;id&quot;</span>:<span class="string">&quot;6&quot;</span>,<span class="attr">&quot;version&quot;</span>:<span class="string">&quot;7.0&quot;</span>,<span class="attr">&quot;name&quot;</span>:<span class="string">&quot;Boom Beach&quot;</span>&#125;,</span><br><span class="line">&#123;<span class="attr">&quot;id&quot;</span>:<span class="string">&quot;7&quot;</span>,<span class="attr">&quot;version&quot;</span>:<span class="string">&quot;3.5&quot;</span>,<span class="attr">&quot;name&quot;</span>:<span class="string">&quot;Clash Royale&quot;</span>&#125;]</span><br></pre></td></tr></table></figure>
<h4 id="使用JSONObject">使用JSONObject<a class="header-anchor" href="#使用JSONObject"> ¶ </a></h4>
<h5 id="转成Json字符串">转成Json字符串<a class="header-anchor" href="#转成Json字符串"> ¶ </a></h5>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// JSONObject转json字符串</span></span><br><span class="line">JSONObject jsonObject = <span class="keyword">new</span> JSONObject();</span><br><span class="line">jsonObject.put(String name,Object value);</span><br><span class="line">jsonObject.put(String name,Object value);</span><br><span class="line"></span><br><span class="line">String jsonStr = jsonObject.toString();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 若是数组，写个循环生成JSONObject，然后用JSONArray对象的put方法</span></span><br></pre></td></tr></table></figure>
<h5 id="读取JSON字符串">读取JSON字符串<a class="header-anchor" href="#读取JSON字符串"> ¶ </a></h5>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">parseJSONWithJSONObject</span><span class="params">(String jsonData)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 读入JSON数组字符串 新建JSONArray对象</span></span><br><span class="line">        JSONArray jsonArray = <span class="keyword">new</span> JSONArray(jsonData);</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; jsonArray.length(); i++) &#123;</span><br><span class="line">            <span class="comment">// 得到json对象</span></span><br><span class="line">            JSONObject jsonObject = jsonArray.getJSONObject(i);</span><br><span class="line">            <span class="comment">// 获得对应数据</span></span><br><span class="line">            String id = jsonObject.getString(<span class="string">&quot;id&quot;</span>);</span><br><span class="line">            String name = jsonObject.getString(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">            String version = jsonObject.getString(<span class="string">&quot;version&quot;</span>);</span><br><span class="line">            Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;id is &quot;</span> + id);</span><br><span class="line">            Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;name is &quot;</span> + name);</span><br><span class="line">            Log.d(<span class="string">&quot;MainActivity&quot;</span>, <span class="string">&quot;version is &quot;</span> + version);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="使用Gson">使用Gson<a class="header-anchor" href="#使用Gson"> ¶ </a></h4>
<h5 id="添加依赖-2">添加依赖<a class="header-anchor" href="#添加依赖-2"> ¶ </a></h5>
<p>编辑<code>app/build.gradle</code>文件，在<code>dependencies</code>闭包中添加</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">compile</span> <span class="string">&#x27;com.google.code.gson:gson:2.8.5&#x27;</span></span><br></pre></td></tr></table></figure>
<h5 id="使用-3">使用<a class="header-anchor" href="#使用-3"> ¶ </a></h5>
<h6 id="Builder设置Gson属性">Builder设置Gson属性<a class="header-anchor" href="#Builder设置Gson属性"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Gson gson = <span class="keyword">new</span> GsonBuilder()</span><br><span class="line">    .serializeNulls()	<span class="comment">// 允许导出null</span></span><br><span class="line">    .setPrettyPrinting()	<span class="comment">// 格式化s</span></span><br><span class="line">    .setDateFormat(<span class="string">&quot;yyyy-MM-dd&quot;</span>)	<span class="comment">// 设置日期输出格式</span></span><br><span class="line">    .create();	<span class="comment">// 生成配置好的Gson对象</span></span><br></pre></td></tr></table></figure>
<h6 id="对象转json字符串">对象转json字符串<a class="header-anchor" href="#对象转json字符串"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Gson gson = <span class="keyword">new</span> Gson();</span><br><span class="line">String jsonStr = gson.toJson(Object);</span><br></pre></td></tr></table></figure>
<h6 id="字符串直接解析对象">字符串直接解析对象<a class="header-anchor" href="#字符串直接解析对象"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">jsonData = <span class="string">&quot;&quot;</span><span class="string">&quot;&#123;&quot;</span>name<span class="string">&quot;:&quot;</span>Tom<span class="string">&quot;,&quot;</span>age<span class="string">&quot;:20&#125;&quot;</span><span class="string">&quot;&quot;</span></span><br><span class="line"><span class="comment">////////////////</span></span><br><span class="line">Gson gson = <span class="keyword">new</span> Gson();</span><br><span class="line">Person person = gson.fromJson(jsonData, Person.class);</span><br></pre></td></tr></table></figure>
<h6 id="Json字符串为对象数组">Json字符串为对象数组<a class="header-anchor" href="#Json字符串为对象数组"> ¶ </a></h6>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;Person&gt; people = gson.fromJson(jsonData, <span class="keyword">new</span> TypeToken&lt;List&lt;Person&gt;&gt;() &#123;&#125;.getType());</span><br></pre></td></tr></table></figure>
<h3 id="网络编程实践">网络编程实践<a class="header-anchor" href="#网络编程实践"> ¶ </a></h3>
<p>定义一个Http工具类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HttpUtil</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 发送Http GET请求</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">sendHttpRequest</span><span class="params">(String address)</span> </span>&#123;</span><br><span class="line">        HttpURLConnection connection = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            URL url = <span class="keyword">new</span> URL(address);</span><br><span class="line"></span><br><span class="line">            connection = (HttpURLConnection) url.openConnection();</span><br><span class="line">            connection.setRequestMethod(<span class="string">&quot;GET&quot;</span>);</span><br><span class="line">            connection.setConnectTimeout(<span class="number">8000</span>);</span><br><span class="line">            connection.setReadTimeout(<span class="number">8000</span>);</span><br><span class="line">            connection.setDoInput(<span class="keyword">true</span>);</span><br><span class="line">            connection.setDoOutput(<span class="keyword">true</span>);</span><br><span class="line">            InputStream in = connection.getInputStream();</span><br><span class="line">            BufferedReader reader = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> InputStreamReader(in));</span><br><span class="line">            StringBuilder response = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">            String line;</span><br><span class="line">            <span class="keyword">while</span> ((line = reader.readLine()) != <span class="keyword">null</span>) &#123;</span><br><span class="line">                response.append(line);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> response.toString();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">return</span> e.getMessage();</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (connection != <span class="keyword">null</span>) &#123;</span><br><span class="line">                connection.disconnect();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 封装好的post请求</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> uri        url</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> parameters 请求参数</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> post请求</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> String <span class="title">sendPost</span><span class="params">(String uri, Map&lt;String, String&gt; parameters)</span> </span>&#123;</span><br><span class="line">        StringBuffer postUrlSB = <span class="keyword">new</span> StringBuffer(serverUrl + uri);</span><br><span class="line">        <span class="keyword">if</span> (parameters != <span class="keyword">null</span>) &#123;</span><br><span class="line">            postUrlSB.append(<span class="string">&quot;?&quot;</span>);</span><br><span class="line">            Set&lt;Map.Entry&lt;String, String&gt;&gt; entries = parameters.entrySet();</span><br><span class="line">            <span class="keyword">int</span> count = <span class="number">1</span>;</span><br><span class="line">            <span class="keyword">int</span> size = parameters.size();</span><br><span class="line">            <span class="keyword">for</span> (Map.Entry&lt;String, String&gt; entry : entries) &#123;</span><br><span class="line">                String key = entry.getKey();</span><br><span class="line">                String value = entry.getValue();</span><br><span class="line">                <span class="keyword">if</span> (count++ &lt; size) &#123;</span><br><span class="line">                    postUrlSB.append(key).append(<span class="string">&quot;=&quot;</span>).append(value).append(<span class="string">&quot;&amp;&quot;</span>);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    postUrlSB.append(key).append(<span class="string">&quot;=&quot;</span>).append(value);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        String postUrl = postUrlSB.toString();</span><br><span class="line">        URL url = <span class="keyword">null</span>;</span><br><span class="line">        HttpURLConnection connection = <span class="keyword">null</span>;</span><br><span class="line">        String meg = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            url = <span class="keyword">new</span> URL(postUrl);</span><br><span class="line">            connection = (HttpURLConnection) url.openConnection();</span><br><span class="line">            connection.setRequestMethod(<span class="string">&quot;POST&quot;</span>);</span><br><span class="line">            connection.setRequestProperty(<span class="string">&quot;Content-type&quot;</span>, <span class="string">&quot;text/plain;charset=UTF-8&quot;</span>);</span><br><span class="line">            InputStream is = connection.getInputStream();</span><br><span class="line">            BufferedReader br = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> InputStreamReader(is));</span><br><span class="line">            meg = br.readLine();</span><br><span class="line">            br.close();</span><br><span class="line">            is.close();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> meg;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>开启子线程来接收返回值</p>
<h4 id="Java回调机制">Java回调机制<a class="header-anchor" href="#Java回调机制"> ¶ </a></h4>
<h5 id="1-定义一个HttpCallbackListener接口">1. 定义一个HttpCallbackListener接口<a class="header-anchor" href="#1-定义一个HttpCallbackListener接口"> ¶ </a></h5>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">HttpCallbackListener</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">onFinish</span><span class="params">(String response)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">onError</span><span class="params">(Exception e)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>onFinish() 方法表示当服务器成功响应我们请求的时候调用：onFinish() 方法中的参数代表着服务器返回的数据。</li>
<li>onError() 表示当进行网络操作出现错误的时候调用：onError() 方法中的参数记录着错误的详细信息。</li>
</ul>
<h5 id="2-修改原HttpUtil类">2.修改原HttpUtil类<a class="header-anchor" href="#2-修改原HttpUtil类"> ¶ </a></h5>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HttpUtil</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">sendHttpRequest</span><span class="params">(<span class="keyword">final</span> String address, <span class="keyword">final</span></span></span></span><br><span class="line"><span class="params"><span class="function">        HttpCallbackListener listener)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line"></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                HttpURLConnection connection = <span class="keyword">null</span>;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    URL url = <span class="keyword">new</span> URL(address);</span><br><span class="line">                    connection = (HttpURLConnection) url.openConnection();</span><br><span class="line">                    connection.setRequestMethod(<span class="string">&quot;GET&quot;</span>);</span><br><span class="line">                    connection.setConnectTimeout(<span class="number">8000</span>);</span><br><span class="line">                    connection.setReadTimeout(<span class="number">8000</span>);</span><br><span class="line">                    connection.setDoInput(<span class="keyword">true</span>);</span><br><span class="line">                    connection.setDoOutput(<span class="keyword">true</span>);</span><br><span class="line">                    InputStream in = connection.getInputStream();</span><br><span class="line">                    BufferedReader reader = <span class="keyword">new</span> BufferedReader(<span class="keyword">new</span> InputStreamReader</span><br><span class="line">                       (in));</span><br><span class="line">                    StringBuilder response = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">                    String line;</span><br><span class="line">                    <span class="keyword">while</span> ((line = reader.readLine()) != <span class="keyword">null</span>) &#123;</span><br><span class="line">                        response.append(line);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">if</span> (listener != <span class="keyword">null</span>) &#123;</span><br><span class="line">                        <span class="comment">// 回调onFinish()方法</span></span><br><span class="line">                        listener.onFinish(response.toString());</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">if</span> (listener != <span class="keyword">null</span>) &#123;</span><br><span class="line">                        <span class="comment">// 回调onError()方法</span></span><br><span class="line">                        listener.onError(e);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                    <span class="keyword">if</span> (connection != <span class="keyword">null</span>) &#123;</span><br><span class="line">                        connection.disconnect();</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;).start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>我们首先给sendHttpRequest() 方法添加了一个HttpCallbackListener 参数</p>
<p>并在方法的内部开启了一个子线程，然后在子线程里去执行具体的网络操作。</p>
<p>子线程中是无法通过return语句来返回数据的，因此这里我们将服务器响应的数据传入了HttpCallbackListener的onFinish() 方法中，如果出现了异常就将异常原因传入到onError() 方法中。<br>
现在sendHttpRequest() 方法接收两个参数了，因此我们在调用它的时候还需要将HttpCallbackListener的实例传入</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">HttpUtil.sendHttpRequest(address, <span class="keyword">new</span> HttpCallbackListener() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onFinish</span><span class="params">(String response)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 在这里根据返回内容执行具体的逻辑</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onError</span><span class="params">(Exception e)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 在这里对异常情况进行处理</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<h4 id="使用OkHttp-2">使用OkHttp<a class="header-anchor" href="#使用OkHttp-2"> ¶ </a></h4>
<p>使用</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HttpUtil</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">sendOkHttpRequest</span><span class="params">(String address, okhttp3.Callback callback)</span> </span>&#123;</span><br><span class="line">        OkHttpClient client = <span class="keyword">new</span> OkHttpClient();</span><br><span class="line">        Request request = <span class="keyword">new</span> Request.Builder()</span><br><span class="line">                .url(address)</span><br><span class="line">                .build();</span><br><span class="line">        client.newCall(request).enqueue(callback);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>okhttp3.Callback ：是OkHttp库中自带的一个回调接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">HttpUtil.sendOkHttpRequest(<span class="string">&quot;http://www.baidu.com&quot;</span>, <span class="keyword">new</span> okhttp3.Callback() &#123;</span><br><span class="line"><span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onResponse</span><span class="params">(Call call, Response response)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        <span class="comment">// 得到服务器返回的具体内容</span></span><br><span class="line">        String responseData = response.body().string();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onFailure</span><span class="params">(Call call, IOException e)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 在这里对异常情况进行处理</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>
<h2 id="Service服务">Service服务<a class="header-anchor" href="#Service服务"> ¶ </a></h2>
<p>服务（Service）是Android中实现程序后台运行的解决方案，它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务</p>
<h3 id="Android多线程">Android多线程<a class="header-anchor" href="#Android多线程"> ¶ </a></h3>
<ol>
<li>
<p>继承Thread类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">extends</span> <span class="title">Thread</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 处理具体的逻辑</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用</span></span><br><span class="line"><span class="keyword">new</span> MyThread().start();</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>实现Runnable接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyThread</span> <span class="keyword">implements</span> <span class="title">Runnable</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 处理具体的逻辑</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用</span></span><br><span class="line">MyThread myThread = <span class="keyword">new</span> MyThread();</span><br><span class="line"><span class="keyword">new</span> Thread(myThread).start();</span><br></pre></td></tr></table></figure>
<p>或者匿名内部类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 处理具体的逻辑</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;).start();</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="异步消息更新UI">异步消息更新UI<a class="header-anchor" href="#异步消息更新UI"> ¶ </a></h4>
<p>定义一个Handler对象，然后实现<code>handleMessage()</code>方法来实现消息接收后更新UI；同时定义Message对象，通过<code>handler.sendMessage()</code>来将消息发soon给给handler进行处理</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> <span class="keyword">implements</span> <span class="title">View</span>.<span class="title">OnClickListener</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> UPDATE_TEXT = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">private</span> TextView text;</span><br><span class="line">    <span class="keyword">private</span> Handler handler = <span class="keyword">new</span> Handler() &#123;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">handleMessage</span><span class="params">(Message msg)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">switch</span> (msg.what) &#123;</span><br><span class="line">                <span class="keyword">case</span> UPDATE_TEXT:</span><br><span class="line">                    <span class="comment">// 在这里可以进行UI操作</span></span><br><span class="line">                    text.setText(<span class="string">&quot;Nice to meet you&quot;</span>);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="keyword">default</span>:</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    ...</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (v.getId()) &#123;</span><br><span class="line">            <span class="keyword">case</span> R.id.change_text:</span><br><span class="line">                <span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">                    <span class="meta">@Override</span></span><br><span class="line">                    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                        Message message = <span class="keyword">new</span> Message();</span><br><span class="line">                        message.what = UPDATE_TEXT;</span><br><span class="line"></span><br><span class="line">                        handler.sendMessage(message); <span class="comment">// 将Message对象发送出去</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;).start();</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h5 id="异步消息处理机制">异步消息处理机制<a class="header-anchor" href="#异步消息处理机制"> ¶ </a></h5>
<ol>
<li>Message<br>
Message是在线程之间传递的消息，它可以在内部携带少量的信息，用于在不同线程之间交换数据。上一小节中我们使用到了Message的what字段，除此之外还可以使用arg1 和arg2字段来携带一些整型数据，使用obj 字段携带一个Object 对象。</li>
<li>Handler<br>
Handler顾名思义也就是处理者的意思，它主要是用于发送和处理消息的。发送消息一般是使用Handler的<code>sendMessage()</code> 方法，而发出的消息经过一系列地辗转处理后，最终会传递到Handler的<code>handleMessage()</code> 方法中。</li>
<li>MessageQueue<br>
MessageQueue是消息队列的意思，它主要用于存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中，等待被处理。每个线程中只会有一个MessageQueue对象。</li>
<li>Looper<br>
Looper是每个线程中的MessageQueue的管家，调用Looper的loop() 方法后，就会进入到一个无限循环当中，然后每当发现MessageQueue中存在一条消息，就会将它取出，并传递到Handler的handleMessage() 方法中。每个线程中也只会有一个Looper 对象。</li>
</ol>
<h4 id="使用AsyncTask类">使用AsyncTask类<a class="header-anchor" href="#使用AsyncTask类"> ¶ </a></h4>
<p>AsyncTask是一个抽象类，要创建一个子类去继承它。</p>
<p>在继承时我们可以为AsyncTask类指定3个泛型参数，这3个参数的用途如下。</p>
<ul>
<li>Params 。在执行AsyncTask时需要传入的参数，可用于在后台任务中使用。</li>
<li>Progress 。后台任务执行时，如果需要在界面上显示当前的进度，则使用这里指定的泛型作为进度单位。</li>
<li>Result 。当任务执行完毕后，如果需要对结果进行返回，则使用这里指定的泛型作为返回值类型</li>
</ul>
<p>重写方法</p>
<ol>
<li>
<p><code>onPreExecute()</code><br>
这个方法会<strong>在后台任务开始执行之前调用</strong>，用于进行一些界面上的初始化操作，比如显示一个进度条对话框等。</p>
</li>
<li>
<p><code>doInBackground(Params...)</code><br>
这个方法中的所有代码都会在子线程中运行，我们应该<strong>在这里去处理所有的耗时任务</strong>。任务一旦完成就可以通过return 语句来将任务的执行结果返回，如果AsyncTask的第三个泛型参数指定的是Void ，就可以不返回任务执行结果。注意，在这个方法中是不可以进行UI操作的，如果需要更新UI元素，比如说反馈当前任务的执行进度，可以调用<code>publishProgress (Progress...) </code>方法来完成。</p>
</li>
<li>
<p><code>onProgressUpdate(Progress...)</code><br>
当在后台任务中调用了<code>publishProgress(Progress...)</code> 方法后，<code>onProgressUpdate (Progress...)</code> 方法就会很快被调用，该方法中携带的参数就是在后台任务中传递过来的。<strong>在这个方法中可以对UI进行操作</strong>，利用参数中的数值就可以对界面元素进行相应的更新。</p>
</li>
<li>
<p><code>onPostExecute(Result)</code><br>
当后台任务<strong>执行完毕并通过return 语句进行返回时</strong>，这个方法就很快会被调用。返回的数据会作为参数传递到此方法中，可以利用返回的数据来进行一些UI操作，比如说提醒任务执行的结果，以及关闭掉进度条对话框等</p>
</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DownloadTask</span> <span class="keyword">extends</span> <span class="title">AsyncTask</span>&lt;<span class="title">Void</span>, <span class="title">Integer</span>, <span class="title">Boolean</span>&gt; </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onPreExecute</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        progressDialog.show(); <span class="comment">// 显示进度对话框</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> Boolean <span class="title">doInBackground</span><span class="params">(Void... params)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">while</span> (<span class="keyword">true</span>) &#123;</span><br><span class="line">                <span class="keyword">int</span> downloadPercent = doDownload(); <span class="comment">// 这是一个虚构的方法</span></span><br><span class="line">                publishProgress(downloadPercent);</span><br><span class="line">                <span class="keyword">if</span> (downloadPercent &gt;= <span class="number">100</span>) &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onProgressUpdate</span><span class="params">(Integer... values)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 在这里更新下载进度</span></span><br><span class="line">        progressDialog.setMessage(<span class="string">&quot;Downloaded &quot;</span> + values[<span class="number">0</span>] + <span class="string">&quot;%&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onPostExecute</span><span class="params">(Boolean result)</span> </span>&#123;</span><br><span class="line">        progressDialog.dismiss(); <span class="comment">// 关闭进度对话框</span></span><br><span class="line">        <span class="comment">// 在这里提示下载结果</span></span><br><span class="line">        <span class="keyword">if</span> (result) &#123;</span><br><span class="line">            Toast.makeText(context, <span class="string">&quot;Download succeeded&quot;</span>, Toast.LENGTH_SHORT).show();</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            Toast.makeText(context, <span class="string">&quot; Download failed&quot;</span>, Toast.LENGTH_SHORT).show();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="Service服务-2">Service服务<a class="header-anchor" href="#Service服务-2"> ¶ </a></h3>
<h4 id="定义一个服务">定义一个服务<a class="header-anchor" href="#定义一个服务"> ¶ </a></h4>
<p>右击新建New→Service→Service；将服务命名为MyService，Exported 属性表示是否允许除了当前程序之外的其他程序访问这个服务，Enabled 属性表示是否启用这个服务。将两个属性都勾中，点击Finish完成创建。</p>
<p>AndroidManifest.xml的application节点内已自动生成Service的声明</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">service</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:name</span>=<span class="string">&quot;.MyService&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:enabled</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">            <span class="attr">android:exported</span>=<span class="string">&quot;true&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">service</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>可添加<code>android:process</code>属性来指定服务创建新进程，示例值：<code>:myservice</code>；则新进程名则为<code>[packagename]:myservice</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyService</span> <span class="keyword">extends</span> <span class="title">Service</span> </span>&#123;</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MyService</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> IBinder <span class="title">onBind</span><span class="params">(Intent intent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> UnsupportedOperationException(<span class="string">&quot;Not yet implemented&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate();</span><br><span class="line">        Log.d(<span class="string">&quot;MyService&quot;</span>, <span class="string">&quot;onCreate executed&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">onStartCommand</span><span class="params">(Intent intent, <span class="keyword">int</span> flags, <span class="keyword">int</span> startId)</span> </span>&#123;</span><br><span class="line">        Log.d(<span class="string">&quot;MyService&quot;</span>, <span class="string">&quot;onStartCommand executed&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">super</span>.onStartCommand(intent, flags, startId);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onDestroy();</span><br><span class="line">        Log.d(<span class="string">&quot;MyService&quot;</span>, <span class="string">&quot;onDestroy executed&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li><code>onCreate()</code> 方法会在服务创建的时候调用</li>
<li><code>onStartCommand()</code> 方法会在每次服务启动的时候调用</li>
<li><code>onDestroy()</code> 方法会在服务销毁的时候调用</li>
</ul>
<h4 id="启动和停止服务">启动和停止服务<a class="header-anchor" href="#启动和停止服务"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">switch</span> (v.getId()) &#123;</span><br><span class="line">        <span class="keyword">case</span> R.id.start_service:</span><br><span class="line">            Intent startIntent = <span class="keyword">new</span> Intent(<span class="keyword">this</span>, MyService.class);</span><br><span class="line">            startService(startIntent); <span class="comment">// 启动服务</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        <span class="keyword">case</span> R.id.stop_service:</span><br><span class="line">            Intent stopIntent = <span class="keyword">new</span> Intent(<span class="keyword">this</span>, MyService.class);</span><br><span class="line">            stopService(stopIntent); <span class="comment">// 停止服务</span></span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>服务自行运行完毕停止：在服务类中根据需要调用<code>stopSelf()</code>方法</p>
<h4 id="活动和服务绑定">活动和服务绑定<a class="header-anchor" href="#活动和服务绑定"> ¶ </a></h4>
<p>创建一个专门的Binder 对象来对下载功能进行管理</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyService</span> <span class="keyword">extends</span> <span class="title">Service</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> DownloadBinder mBinder = <span class="keyword">new</span> DownloadBinder();</span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">DownloadBinder</span> <span class="keyword">extends</span> <span class="title">Binder</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">startDownload</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            Log.d(<span class="string">&quot;MyService&quot;</span>, <span class="string">&quot;startDownload executed&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getProgress</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            Log.d(<span class="string">&quot;MyService&quot;</span>, <span class="string">&quot;getProgress executed&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> IBinder <span class="title">onBind</span><span class="params">(Intent intent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> mBinder;</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>当一个活动和服务绑定了之后，就可以调用该服务里的Binder 提供的方法了</p>
<p><strong>活动</strong>创建了一个<code>ServiceConnection</code> 的匿名类，在里面重写了<code>onServiceConnected()</code>方法和<code>onServiceDisconnected()</code> 方法，这两个方法分别会在<em>活动与服务成功绑定</em>以及<em>活动与服务的连接断开</em>的时候调用</p>
<p>构建出了一个Intent 对象，然后调用bindService() 方法将MainActivity和MyService进行绑定。</p>
<p>bindService() 方法接收3个参数：</p>
<ul>
<li>第一个参数就是刚刚构建出的Intent 对象</li>
<li>第二个参数是前面创建出的ServiceConnection的实例</li>
<li>第三个参数则是一个标志位，这里传<code>入BIND_AUTO_CREATE</code> 表示在活动和服务进行绑定后自动创建服务。这会使得MyService中的onCreate() 方法得到执行，<strong>但onStartCommand() 方法不会执行</strong></li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> <span class="keyword">implements</span> <span class="title">View</span>.<span class="title">OnClickListener</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> MyService.DownloadBinder downloadBinder;</span><br><span class="line">    <span class="keyword">private</span> ServiceConnection connection = <span class="keyword">new</span> ServiceConnection() &#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onServiceDisconnected</span><span class="params">(ComponentName name)</span> </span>&#123;</span><br><span class="line">            <span class="comment">// 非正常情况下服务被终止执行</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onServiceConnected</span><span class="params">(ComponentName name, IBinder service)</span> </span>&#123;</span><br><span class="line">            <span class="comment">// 绑定服务成功以后执行</span></span><br><span class="line">            downloadBinder = (MyService.DownloadBinder) service;</span><br><span class="line">            downloadBinder.startDownload();</span><br><span class="line">            downloadBinder.getProgress();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        ...</span><br><span class="line"></span><br><span class="line">        Button bindService = (Button) findViewById(R.id.bind_service);</span><br><span class="line">        Button unbindService = (Button) findViewById(R.id.unbind_service);</span><br><span class="line">        bindService.setOnClickListener(<span class="keyword">this</span>);</span><br><span class="line">        unbindService.setOnClickListener(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onClick</span><span class="params">(View v)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (v.getId()) &#123;</span><br><span class="line">            ...</span><br><span class="line">            <span class="keyword">case</span> R.id.bind_service:</span><br><span class="line">                Intent bindIntent = <span class="keyword">new</span> Intent(<span class="keyword">this</span>, MyService.class);</span><br><span class="line">                bindService(bindIntent, connection, BIND_AUTO_CREATE); <span class="comment">// 绑定服务</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">case</span> R.id.unbind_service:</span><br><span class="line">                unbindService(connection); <span class="comment">// 解绑服务</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="服务Service的生命周期">服务Service的生命周期<a class="header-anchor" href="#服务Service的生命周期"> ¶ </a></h4>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/Service%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.png" alt="img"></p>
<p>一旦在项目的任何位置调用了Context的startService() 方法，相应的服务就会启动起来，并回调onStartCommand() 方法。</p>
<p>如果这个服务之前还没有创建过，onCreate() 方法会先于onStartCommand() 方法执行。服务启动了之后会一直保持运行状态，直到stopService()或stopSelf() 方法被调用。</p>
<p>注意，虽然每调用一次startService() 方法，onStartCommand() 就会执行一次，但实际上<strong>每个服务都只会存在一个实例</strong>。所以不管你调用了多少次startService()方法，只需调用一次stopService() 或stopSelf()方法，服务就会停止下来了。</p>
<p>另外，还可以调用Context的bindService() 来获取一个服务的持久连接，这时就会回调服务中的onBind() 方法。</p>
<p>类似地，如果这个服务之前还没有创建过，onCreate() 方法会先于onBind() 方法执行。之后，调用方可以获取到onBind() 方法里返回的IBinder 对象的实例，这样就能自由地和服务进行通信了。只要调用方和服务之间的连接没有断开，服务就会一直保持运行状态。<br>
当调用了startService() 方法后，又去调用stopService() 方法，这时服务中的onDestroy()方法就会执行，表示服务已经销毁了。类似地，当调用了bindService() 方法后，又去调用unbindService() 方法，onDestroy() 方法也会执行，这两种情况都很好理解。</p>
<p>但是需要注意，我们是完全有可能对一个服务既调用了startService() 方法，又调用了bindService() 方法的，这种情况下该如何才能让服务销毁掉呢？根据Android系统的机制，一个服务只要被启动或者被绑定了之后，就会一直处于运行状态，必须要让以上两种条件同时不满足，服务才能被销毁。所以，这种情况下要同时调用stopService()和unbindService() 方法，onDestroy() 方法才会执行。</p>
<h3 id="服务的更多技巧">服务的更多技巧<a class="header-anchor" href="#服务的更多技巧"> ¶ </a></h3>
<h3 id="使用前台服务">使用前台服务<a class="header-anchor" href="#使用前台服务"> ¶ </a></h3>
<p>只是创建通知后，调用<code>startForeground()</code>对象来显示前台服务</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyService</span> <span class="keyword">extends</span> <span class="title">Service</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    ...</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate();</span><br><span class="line">        Log.d(<span class="string">&quot;MyService&quot;</span>, <span class="string">&quot;onCreate executed&quot;</span>);</span><br><span class="line">        Intent intent = <span class="keyword">new</span> Intent(<span class="keyword">this</span>, MainActivity.class);</span><br><span class="line">        PendingIntent pi = PendingIntent.getActivity(<span class="keyword">this</span>, <span class="number">0</span>, intent, <span class="number">0</span>);</span><br><span class="line">        Notification notification = <span class="keyword">new</span> NotificationCompat.Builder(<span class="keyword">this</span>)</span><br><span class="line">                .setContentTitle(<span class="string">&quot;This is content title&quot;</span>)</span><br><span class="line">                .setContentText(<span class="string">&quot;This is content text&quot;</span>)</span><br><span class="line">                .setWhen(System.currentTimeMillis())</span><br><span class="line">                .setSmallIcon(R.mipmap.ic_launcher)</span><br><span class="line">                .setLargeIcon(BitmapFactory.decodeResource(getResources(),</span><br><span class="line">                    R.mipmap.ic_launcher))</span><br><span class="line">                .setContentIntent(pi)</span><br><span class="line">                .build();</span><br><span class="line">        startForeground(<span class="number">1</span>, notification);</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="使用IntentService">使用IntentService<a class="header-anchor" href="#使用IntentService"> ¶ </a></h4>
<p>应该在服务的每个具体的方法里开启一个子线程，然后在这里去处理那些耗时的逻辑</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyService</span> <span class="keyword">extends</span> <span class="title">Service</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">onStartCommand</span><span class="params">(Intent intent, <span class="keyword">int</span> flags, <span class="keyword">int</span> startId)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 处理具体的逻辑</span></span><br><span class="line">                stopSelf();	<span class="comment">// 在子线程中添加该语句，可让服务执行完后自行停止</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;).start();</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">super</span>.onStartCommand(intent, flags, startId);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>或者简单的 继承<code>IntentService</code>类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyIntentService</span> <span class="keyword">extends</span> <span class="title">IntentService</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MyIntentService</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(<span class="string">&quot;MyIntentService&quot;</span>); <span class="comment">// 调用父类的有参构造函数</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onHandleIntent</span><span class="params">(Intent intent)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 在当前方法中处理耗时逻辑</span></span><br><span class="line">        <span class="comment">// 打印当前线程的id</span></span><br><span class="line">        Log.d(<span class="string">&quot;MyIntentService&quot;</span>, <span class="string">&quot;Thread id is &quot;</span> + Thread.currentThread(). getId());</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onDestroy();</span><br><span class="line">        Log.d(<span class="string">&quot;MyIntentService&quot;</span>, <span class="string">&quot;onDestroy executed&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>要在子类中去实现<code>onHandleIntent()</code> 这个抽象方法，在这个方法中可以去处理一些具体的逻辑，而且不用担心ANR的问题，因为这个方法已经是在子线程中运行的了。另外根据ntentService 的特性，<strong>这个服务在运行结束后应该是会自动停止</strong>的，所以我们又重写了<code>onDestroy()</code> 方法，在这里也打印了一行日志，以证实服务是不是停止掉了</p>
<h4 id="使用JobService">使用JobService<a class="header-anchor" href="#使用JobService"> ¶ </a></h4>
<p>Android8.0(26)之后推荐使用JobService</p>
<p>重写方法变为<code>onHandleWork()</code></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyJobIntentService</span> <span class="keyword">extends</span> <span class="title">JobIntentService</span> </span>&#123;</span><br><span class="line">    <span class="comment">// JobIntentService会使用单独的线程来执行该方法的代码</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onHandleWork</span><span class="params">(Intent intent)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 该方法内可以执行任何耗时任务，比如下载文件等，此处只是让线程暂停20秒</span></span><br><span class="line">        <span class="keyword">long</span> endTime = System.currentTimeMillis() + <span class="number">20</span> * <span class="number">1000</span>;</span><br><span class="line">        <span class="keyword">while</span> (System.currentTimeMillis() &lt; endTime) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (<span class="keyword">this</span>) &#123;</span><br><span class="line">	         <span class="keyword">try</span> &#123;</span><br><span class="line">	             wait(endTime - System.currentTimeMillis());</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 耗时任务执行完成</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>AndroidManifest.xml中配置Service</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">service</span> <span class="attr">android:name</span>=<span class="string">&quot;.MyJobIntentService&quot;</span> <span class="attr">android:permission</span>=<span class="string">&quot;android.permission.BIND_JOB_SERVICE&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!--android.permission.BIND_JOB_SERVICE这个权限一定要有，否则程序会崩溃--&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">service</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>启动服务</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) &#123;</span><br><span class="line">    <span class="keyword">int</span> JOB_ID = <span class="number">88</span>;</span><br><span class="line">    Intent work  = <span class="keyword">new</span> Intent();</span><br><span class="line">    work.putExtra(<span class="string">&quot;key&quot;</span>,<span class="string">&quot;value&quot;</span>);</span><br><span class="line">    MyJobIntentService.enqueueWork(MainActivity.<span class="keyword">this</span>,</span><br><span class="line">        MyJobIntentService.class,JOB_ID, work);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="服务的最佳实践——完整版的下载示例">服务的最佳实践——完整版的下载示例<a class="header-anchor" href="#服务的最佳实践——完整版的下载示例"> ¶ </a></h3>
<p>@TODO</p>
<h2 id="基于位置的服务">基于位置的服务<a class="header-anchor" href="#基于位置的服务"> ¶ </a></h2>
<h3 id="百度地图API">百度地图API<a class="header-anchor" href="#百度地图API"> ¶ </a></h3>
<h4 id="申请API">申请API<a class="header-anchor" href="#申请API"> ¶ </a></h4>
<p>前往<a target="_blank" rel="noopener" href="http://developer.baidu.com/user/reg">百度开放服务平台 (baidu.com)</a>注册开发者</p>
<p>来到<a target="_blank" rel="noopener" href="https://lbsyun.baidu.com/apiconsole/key">控制台 | 百度地图开放平台 (baidu.com)</a>创建应用</p>
<p>应用名称随意，应用类型选择【Android SDK】</p>
<h5 id="获取开发版-debug-SHA1">获取开发版(debug) SHA1<a class="header-anchor" href="#获取开发版-debug-SHA1"> ¶ </a></h5>
<p>前往系统的<code>.android</code>目录，默认位于<code>~/.android</code></p>
<p>输入命令</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">E:\code\Android\.android&gt;keytool -list -v -keystore debug.keystore</span><br><span class="line">输入密钥库口令:</span><br><span class="line">密钥库类型: jks</span><br><span class="line">密钥库提供方: SUN</span><br><span class="line"></span><br><span class="line">您的密钥库包含 1 个条目</span><br><span class="line"></span><br><span class="line">别名: androiddebugkey</span><br><span class="line">创建日期: 2021-2-27</span><br><span class="line">条目类型: PrivateKeyEntry</span><br><span class="line">证书链长度: 1</span><br><span class="line">证书[1]:</span><br><span class="line">所有者: C=US, O=Android, CN=Android Debug</span><br><span class="line">发布者: C=US, O=Android, CN=Android Debug</span><br><span class="line">序列号: 1</span><br><span class="line">有效期为 Sat Feb 27 18:40:11 CST 2021 至 Mon Feb 20 18:40:11 CST 2051</span><br><span class="line">证书指纹:</span><br><span class="line">         MD5:  84:9D:C6:94:D8:2F:C2:90:00:00:00:00:00:00:00:00</span><br><span class="line">         SHA1: D2:4C:7C:89:85:83:9A:68:1C:6F:FF:0F:00:00:00:00:00:00:00:00</span><br><span class="line">         SHA256: EF:5A:67:E6:15:68:64:05:AD:95:90:7F:0F:5C:34:2B:79:54:15:C0:85:94:1E:9B:00:00:00:00:00:00:00:00</span><br><span class="line">签名算法名称: SHA1withRSA</span><br><span class="line">主体公共密钥算法: 2048 位 RSA 密钥</span><br><span class="line">版本: 1</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">*******************************************</span><br><span class="line">*******************************************</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Warning:</span><br><span class="line">JKS 密钥库使用专用格式。建议使用 <span class="string">&quot;keytool -importkeystore -srckeystore debug.keystore -destkeystore debug.keystore -deststoretype pkcs12&quot;</span> 迁移到行业标准格式 PKCS12。</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h5 id="获取发布板-release-SHA1">获取发布板(release) SHA1<a class="header-anchor" href="#获取发布板-release-SHA1"> ¶ </a></h5>
<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/zhangmiao14/p/7274977.html">Android百度地图开发-第一篇：申请、搭建百度地图 - zhangmiao14 - 博客园 (cnblogs.com)</a>创建相应的签名文件，并获取相应的SHA1</p>
<p>(测试，可以相同)</p>
<h5 id="包名正常设置">包名正常设置<a class="header-anchor" href="#包名正常设置"> ¶ </a></h5>
<h5 id="点击提交">点击提交<a class="header-anchor" href="#点击提交"> ¶ </a></h5>
<h5 id="可复制key，或者-设置-修改上述配置">可复制key，或者[设置]修改上述配置<a class="header-anchor" href="#可复制key，或者-设置-修改上述配置"> ¶ </a></h5>
<h3 id="使用百度定位">使用百度定位<a class="header-anchor" href="#使用百度定位"> ¶ </a></h3>
<p>官方开发文档：<a target="_blank" rel="noopener" href="https://lbs.baidu.com/index.php?title=androidsdk">Android地图SDK | 百度地图API SDK (baidu.com)</a></p>
<h5 id="下载-配置SDK">下载&amp;配置SDK<a class="header-anchor" href="#下载-配置SDK"> ¶ </a></h5>
<h6 id="下载SDK">下载SDK<a class="header-anchor" href="#下载SDK"> ¶ </a></h6>
<p><a target="_blank" rel="noopener" href="https://lbs.baidu.com/index.php?title=sdk/download&amp;action#selected=mapsdk_basicmap,mapsdk_searchfunction,mapsdk_lbscloudsearch,mapsdk_calculationtool,mapsdk_radar">SDK下载 - 百度LBS开放平台 (baidu.com)</a></p>
<p>（根据需要）选择基础定位和基础地图，选择jar格式、标准开发包选择下载</p>
<h6 id="配置SDK">配置SDK<a class="header-anchor" href="#配置SDK"> ¶ </a></h6>
<p>解压下载的jar包，然后进入<code>libs</code>目录</p>
<p>选择其中的<code>BaiduLBS_Android.jar</code>文件放入项目中<code>app/libs</code>目录</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// gradle中需配置</span></span><br><span class="line"></span><br><span class="line">dependencies &#123;</span><br><span class="line">    <span class="function">implementation <span class="title">fileTree</span><span class="params">(dir: <span class="string">&#x27;libs&#x27;</span>, include: [<span class="string">&#x27;*.jar&#x27;</span>])</span></span></span><br><span class="line"><span class="function">    ...</span></span><br><span class="line"><span class="function">&#125;</span></span><br></pre></td></tr></table></figure>
<p>之后新建<code>src/main/jniLibs</code>目录，将 剩余所有 复制到此处</p>
<h5 id="项目配置">项目配置<a class="header-anchor" href="#项目配置"> ¶ </a></h5>
<h6 id="AndroidManifest配置">AndroidManifest配置<a class="header-anchor" href="#AndroidManifest配置"> ¶ </a></h6>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">manifest</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">package</span>=<span class="string">&quot;com.example.lbstest&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 添加权限：start --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.ACCESS_COARSE_LOCATION&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.ACCESS_FINE_LOCATION&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.ACCESS_WIFI_STATE&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.ACCESS_NETWORK_STATE&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.CHANGE_WIFI_STATE&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.READ_PHONE_STATE&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.INTERNET&quot;</span>/&gt;</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">&lt;!-- 可删去 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.MOUNT_UNMOUNT_FILESYSTEMS&quot;</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.WAKE_LOCK&quot;</span>/&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 添加权限：end --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">application</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:allowBackup</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:icon</span>=<span class="string">&quot;@mipmap/ic_launcher&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:label</span>=<span class="string">&quot;@string/app_name&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:supportsRtl</span>=<span class="string">&quot;true&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:theme</span>=<span class="string">&quot;@style/AppTheme&quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 添加key：start 需要修改value为申请到的key值 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">meta-data</span>  </span></span><br><span class="line"><span class="tag">            <span class="attr">android:name</span>=<span class="string">&quot;com.baidu.lbsapi.API_KEY&quot;</span>  </span></span><br><span class="line"><span class="tag">            <span class="attr">android:value</span>=<span class="string">&quot;开发者 key&quot;</span> /&gt;</span>  </span><br><span class="line">        <span class="comment">&lt;!-- 添加key：end --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">activity</span> <span class="attr">android:name</span>=<span class="string">&quot;.MainActivity&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">intent-filter</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">action</span> <span class="attr">android:name</span>=<span class="string">&quot;android.intent.action.MAIN&quot;</span> /&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">category</span> <span class="attr">android:name</span>=<span class="string">&quot;android.intent.category.LAUNCHER&quot;</span> /&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">intent-filter</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">activity</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">service</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">application</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">manifest</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h5 id="代码">代码<a class="header-anchor" href="#代码"> ¶ </a></h5>
<p><a name="runtime_permission">动态申请权限代码示例</a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> LocationClient mLocationClient;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> TextView positionText;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        mLocationClient = <span class="keyword">new</span> LocationClient(getApplicationContext());</span><br><span class="line">        <span class="comment">// 注册一个定位监听器，当获得位置时，就会回调该监听器</span></span><br><span class="line">        mLocationClient.registerLocationListener(<span class="keyword">new</span> MyLocationListener());</span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line">        positionText = (TextView) findViewById(R.id.position_text_view);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//动态申请权限</span></span><br><span class="line">        <span class="comment">// 申请权限较多，建立权限数组</span></span><br><span class="line">        List&lt;String&gt; permissionList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        <span class="comment">// 如果没有该权限，就将该权限添加到权限数组中</span></span><br><span class="line">        <span class="keyword">if</span> (ContextCompat.checkSelfPermission(MainActivity.<span class="keyword">this</span>, Manifest.</span><br><span class="line">            permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED) &#123;</span><br><span class="line">            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (ContextCompat.checkSelfPermission(MainActivity.<span class="keyword">this</span>, Manifest.</span><br><span class="line">            permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) &#123;</span><br><span class="line">            permissionList.add(Manifest.permission.READ_PHONE_STATE);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (ContextCompat.checkSelfPermission(MainActivity.<span class="keyword">this</span>, Manifest.</span><br><span class="line">            permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) &#123;</span><br><span class="line">            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 如果权限数组不为空，则证明有权限未申请</span></span><br><span class="line">        <span class="keyword">if</span> (!permissionList.isEmpty()) &#123;</span><br><span class="line">            <span class="comment">// 将该申请的权限转换为String[]数组</span></span><br><span class="line">            String [] permissions = permissionList.toArray(<span class="keyword">new</span> String[permissionList.</span><br><span class="line">                size()]);</span><br><span class="line">            <span class="comment">// 进行权限的申请</span></span><br><span class="line">            ActivityCompat.requestPermissions(MainActivity.<span class="keyword">this</span>, permissions, <span class="number">1</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"></span><br><span class="line">            requestLocation();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">requestLocation</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        mLocationClient.start();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onRequestPermissionsResult</span><span class="params">(<span class="keyword">int</span> requestCode, String[] permissions,</span></span></span><br><span class="line"><span class="params"><span class="function">        <span class="keyword">int</span>[] grantResults)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">switch</span> (requestCode) &#123;</span><br><span class="line">            <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">                <span class="keyword">if</span> (grantResults.length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                    <span class="keyword">for</span> (<span class="keyword">int</span> result : grantResults) &#123;</span><br><span class="line">                        <span class="keyword">if</span> (result != PackageManager.PERMISSION_GRANTED) &#123;</span><br><span class="line">                            Toast.makeText(<span class="keyword">this</span>, <span class="string">&quot;必须同意所有权限才能使用本程序&quot;</span>,</span><br><span class="line">                                Toast.LENGTH_SHORT).show();</span><br><span class="line">                            <span class="comment">// 如果有权限未被同意，则退出程序</span></span><br><span class="line">                            finish();</span><br><span class="line">                            <span class="keyword">return</span>;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="comment">//同意所有权限后，加载位置</span></span><br><span class="line">                    requestLocation();</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    Toast.makeText(<span class="keyword">this</span>, <span class="string">&quot;发生未知错误&quot;</span>, Toast.LENGTH_SHORT).show();</span><br><span class="line">                    finish();</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 获得相应参数</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyLocationListener</span> <span class="keyword">implements</span> <span class="title">BDLocationListener</span> </span>&#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceiveLocation</span><span class="params">(BDLocation location)</span> </span>&#123;</span><br><span class="line">            runOnUiThread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">                <span class="meta">@Override</span></span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                    StringBuilder currentPosition = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">                    currentPosition.append(<span class="string">&quot;纬度：&quot;</span>).append(location.getLatitude()).</span><br><span class="line"></span><br><span class="line">                        append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">                    currentPosition.append(<span class="string">&quot;经线：&quot;</span>).append(location.getLongitude()).</span><br><span class="line">                        append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">                    currentPosition.append(<span class="string">&quot;定位方式：&quot;</span>);</span><br><span class="line">                    <span class="keyword">if</span> (location.getLocType() == BDLocation.TypeGpsLocation) &#123;</span><br><span class="line">                        currentPosition.append(<span class="string">&quot;GPS&quot;</span>);</span><br><span class="line">                    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (location.getLocType() ==</span><br><span class="line">                        BDLocation.TypeNetWorkLocation) &#123;</span><br><span class="line">                        currentPosition.append(<span class="string">&quot;网络&quot;</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                    positionText.setText(currentPosition);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onConnectHotSpotMessage</span><span class="params">(String s, <span class="keyword">int</span> i)</span> </span>&#123;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h5 id="实时更新位置">实时更新位置<a class="header-anchor" href="#实时更新位置"> ¶ </a></h5>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">requestLocation</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        initLocation();</span><br><span class="line">        mLocationClient.start();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">initLocation</span><span class="params">()</span></span>&#123;</span><br><span class="line">        LocationClientOption option = <span class="keyword">new</span> LocationClientOption();</span><br><span class="line">        option.setScanSpan(<span class="number">5000</span>);</span><br><span class="line">        mLocationClient.setLocOption(option);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onDestroy();</span><br><span class="line"></span><br><span class="line">        mLocationClient.stop();</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="选择定位模式">选择定位模式<a class="header-anchor" href="#选择定位模式"> ¶ </a></h4>
<p>上述方式为网络定位</p>
<p>切换到GPS定位。手机设置：位置信息模式→高精确度</p>
<blockquote>
<p>定位模式进行指定，一共有3种模式可选：Hight_Accuracy、Battery_Saving和Device_Sensors。</p>
<p>Hight_Accuracy表示高精确度模式，会在GPS信号正常的情况下优先使用GPS定位，在无法接收GPS信号的时候使用网络定位。</p>
<p>Battery_Saving表示节电模式，只会使用网络进行定位。</p>
<p>Device_Sensors表示传感器模式，只会使用GPS进行定位。</p>
<p>其中，Hight_Accuracy是默认的模式。</p>
</blockquote>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">initLocation</span><span class="params">()</span></span>&#123;</span><br><span class="line">        LocationClientOption option = <span class="keyword">new</span> LocationClientOption();</span><br><span class="line">        option.setScanSpan(<span class="number">5000</span>);</span><br><span class="line">        <span class="comment">// 设置定位模式</span></span><br><span class="line">        option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);</span><br><span class="line">        mLocationClient.setLocOption(option);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="显示位置相关信息">显示位置相关信息<a class="header-anchor" href="#显示位置相关信息"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 设置LocationClientOption的 需要获取当前位置详细的地址信息</span></span><br><span class="line">option.setIsNeedAddress(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">StringBuilder currentPosition = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">currentPosition.append(<span class="string">&quot;纬度：&quot;</span>).append(location.getLatitude()).</span><br><span class="line">append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">currentPosition.append(<span class="string">&quot;经线：&quot;</span>).append(location.getLongitude()).</span><br><span class="line">append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">currentPosition.append(<span class="string">&quot;国家：&quot;</span>).append(location.getCountry()).</span><br><span class="line">append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">currentPosition.append(<span class="string">&quot;省：&quot;</span>).append(location.getProvince()).</span><br><span class="line">append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">currentPosition.append(<span class="string">&quot;市：&quot;</span>).append(location.getCity()).</span><br><span class="line">append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">currentPosition.append(<span class="string">&quot;区：&quot;</span>).append(location.getDistrict()).</span><br><span class="line">append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">currentPosition.append(<span class="string">&quot;街道：&quot;</span>).append(location.getStreet()).</span><br><span class="line">append(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">currentPosition.append(<span class="string">&quot;定位方式：&quot;</span>);</span><br><span class="line"><span class="keyword">if</span> (location.getLocType() == BDLocation.TypeGpsLocation) &#123;</span><br><span class="line">currentPosition.append(<span class="string">&quot;GPS&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (location.getLocType() ==</span><br><span class="line">BDLocation.TypeNetWorkLocation) &#123;</span><br><span class="line">currentPosition.append(<span class="string">&quot;网络&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">positionText.setText(currentPosition);</span><br></pre></td></tr></table></figure>
<h3 id="使用百度地图">使用百度地图<a class="header-anchor" href="#使用百度地图"> ¶ </a></h3>
<p>添加地图控件</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">com.baidu.mapapi.map.MapView</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/bmapView&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:clickable</span>=<span class="string">&quot;true&quot;</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<p>添加Application继承类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyApplication</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate();</span><br><span class="line">        <span class="comment">//初始化百度地图</span></span><br><span class="line">        SDKInitializer.initialize(<span class="keyword">this</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * 同时使AndroidManifest中&lt;application&gt;节点的 name属性为该类</span></span><br></pre></td></tr></table></figure>
<p>java代码实现</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">private</span> MapView mapView;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        <span class="comment">// 初始化要在 setContentView 前</span></span><br><span class="line">        mLocationClient = <span class="keyword">new</span> LocationClient(getApplicationContext());</span><br><span class="line">        mLocationClient.registerLocationListener(<span class="keyword">new</span> MyLocationListener());</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 添加下面这个，就不用添加自定义Application类了</span></span><br><span class="line">        SDKInitializer.initialize(getApplication());</span><br><span class="line">        </span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line"></span><br><span class="line">        mapView = (MapView) findViewById(R.id.bmapView);</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 重写相应方法，及时释放资源</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onResume</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onResume();</span><br><span class="line">        mapView.onResume();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onPause</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onPause();</span><br><span class="line">        mapView.onPause();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onDestroy();</span><br><span class="line"></span><br><span class="line">        mLocationClient.stop();</span><br><span class="line">        mapView.onDestroy();</span><br><span class="line">    &#125;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="定位到当前位置">定位到当前位置<a class="header-anchor" href="#定位到当前位置"> ¶ </a></h4>
<p>先获得地图总控制器</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">BaiduMap baiduMap = mapView.getMap();</span><br></pre></td></tr></table></figure>
<ol>
<li>
<p>设置缩放级别</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 设置缩放级别(3~21)，值越大地图越精细</span></span><br><span class="line">MapStatusUpdate update = MapStatusUpdateFactory.zoomTo(<span class="number">12.5f</span>);</span><br><span class="line"><span class="comment">// 最后需要调用该方法 使update的设置生效</span></span><br><span class="line">baiduMap.animateMapStatus(update);</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>设置经纬度</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">LatLng ll = <span class="keyword">new</span> LatLng(<span class="number">39.915</span>, <span class="number">116.404</span>);</span><br><span class="line">MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);</span><br><span class="line">baiduMap.animateMapStatus(update);</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="显示所在位置光标">显示所在位置光标<a class="header-anchor" href="#显示所在位置光标"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainActivity</span> <span class="keyword">extends</span> <span class="title">AppCompatActivity</span> </span>&#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">private</span> BaiduMap baiduMap;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">boolean</span> isFirstLocate = <span class="keyword">true</span>;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        <span class="comment">// 初始化要在 setContentView 前</span></span><br><span class="line">        mLocationClient = <span class="keyword">new</span> LocationClient(getApplicationContext());</span><br><span class="line">        mLocationClient.registerLocationListener(<span class="keyword">new</span> MyLocationListener());</span><br><span class="line">        </span><br><span class="line">        setContentView(R.layout.activity_main);</span><br><span class="line"></span><br><span class="line">        mapView = (MapView) findViewById(R.id.bmapView);</span><br><span class="line">        <span class="comment">// 获得Map控制器</span></span><br><span class="line">        baiduMap = mapView.getMap();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 启用我的位置显示</span></span><br><span class="line">        baiduMap.setMyLocationEnabled(<span class="keyword">true</span>);</span><br><span class="line">        ...</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">navigateTo</span><span class="params">(BDLocation location)</span> </span>&#123;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">         * 地图定位到当前位置</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">// 判断是不是第一次定位</span></span><br><span class="line">        <span class="comment">// 定位到当前位置，同时设置精度</span></span><br><span class="line">        <span class="keyword">if</span> (isFirstLocate) &#123;</span><br><span class="line">            LatLng ll = <span class="keyword">new</span> LatLng(location.getLatitude(), location.getLongitude());</span><br><span class="line">            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);</span><br><span class="line">            baiduMap.animateMapStatus(update);</span><br><span class="line">            update = MapStatusUpdateFactory.zoomTo(<span class="number">16f</span>);</span><br><span class="line">            baiduMap.animateMapStatus(update);</span><br><span class="line">            isFirstLocate = <span class="keyword">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">/*</span></span><br><span class="line"><span class="comment">         * 地图上当前位置 显示我的图标</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="comment">// 封装设备当前所在位置</span></span><br><span class="line">        MyLocationData.Builder locationBuilder = <span class="keyword">new</span> MyLocationData.Builder();</span><br><span class="line">        locationBuilder.latitude(location.getLatitude());</span><br><span class="line">        locationBuilder.longitude(location.getLongitude());</span><br><span class="line">        MyLocationData locationData = locationBuilder.build();</span><br><span class="line">        <span class="comment">// 设置上“我的位置”</span></span><br><span class="line">        baiduMap.setMyLocationData(locationData);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyLocationListener</span> <span class="keyword">implements</span> <span class="title">BDLocationListener</span> </span>&#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onReceiveLocation</span><span class="params">(BDLocation location)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (location.getLocType() == BDLocation.TypeGpsLocation</span><br><span class="line">                || location.getLocType() == BDLocation.TypeNetWorkLocation) &#123;</span><br><span class="line">                <span class="comment">// 初始化地图</span></span><br><span class="line">                navigateTo(location);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onDestroy</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onDestroy();</span><br><span class="line">        mLocationClient.stop();</span><br><span class="line">        mapView.onDestroy();</span><br><span class="line">        <span class="comment">// 关闭我的位置显示，节约资源</span></span><br><span class="line">        baiduMap.setMyLocationEnabled(<span class="keyword">false</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="最佳的UI体验——MaterialDesign实战">最佳的UI体验——MaterialDesign实战<a class="header-anchor" href="#最佳的UI体验——MaterialDesign实战"> ¶ </a></h2>
<h3 id="Toolbar">Toolbar<a class="header-anchor" href="#Toolbar"> ¶ </a></h3>
<p>项目主题由AndroidManifest中的android:theme指定，默认继承的<code>Theme.AppCompat.Light.DarkActionBar</code>含有ActionBar</p>
<p>指定一个不带ActionBar的主题：<code>Theme.AppCompat.NoActionBar</code>(深色主题) 和<code>Theme.AppCompat.Light.NoActionBar</code>(浅色主题)这两种主题可选</p>
<p>而AppTheme的style中指定的item有以下几种</p>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/ThemeStyleColor.jpg" alt="ThemeStyleColor"></p>
<p>使用TooBar</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">FrameLayout</span> <span class="attr">xmlns:android</span>=<span class="string">&quot;http://schemas.android.com/apk/res/android&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">xmlns:app</span>=<span class="string">&quot;http://schemas.android.com/apk/res-auto&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">android.support.v7.widget.Toolbar</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">&quot;@+id/toolbar&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">&quot;?attr/actionBarSize&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:background</span>=<span class="string">&quot;?attr/colorPrimary&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:theme</span>=<span class="string">&quot;@style/ThemeOverlay.AppCompat.Dark.ActionBar&quot;</span></span></span><br><span class="line"><span class="tag">        <span class="attr">app:popupTheme</span>=<span class="string">&quot;@style/ThemeOverlay.AppCompat.Light&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">FrameLayout</span>&gt;</span></span><br></pre></td></tr></table></figure>
<p>使用xmlns:app 指定了一个新的命名空间。由于Material Design是在Android 5.0系统中才出现的，而很多的Material属性在5.0之前的系统中并不存在，那么为了能够兼容之前的老系统，我们就不能使用android:attribute 这样的写法了，而是应该使用app:attribute 。</p>
<h2 id="继续进阶—应该掌握的高级技巧">继续进阶—应该掌握的高级技巧<a class="header-anchor" href="#继续进阶—应该掌握的高级技巧"> ¶ </a></h2>
<h3 id="全局获取Context技巧">全局获取Context技巧<a class="header-anchor" href="#全局获取Context技巧"> ¶ </a></h3>
<p>定义一个MyApp类，继承Application</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyApplication</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Context context;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        context = getApplicationContext();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> Context <span class="title">getContext</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> context;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>指定name属性<code>&lt;application         android:name=&quot;MyApplication&quot;         ...&gt;</code></p>
<h3 id="使用Intent传递对象">使用Intent传递对象<a class="header-anchor" href="#使用Intent传递对象"> ¶ </a></h3>
<h4 id="Serializable方式">Serializable方式<a class="header-anchor" href="#Serializable方式"> ¶ </a></h4>
<p>直接让实体类实现Serializable接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Person</span> <span class="keyword">implements</span> <span class="title">Serializable</span></span>&#123;</span><br></pre></td></tr></table></figure>
<p>传递时</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Person person = <span class="keyword">new</span> Person();</span><br><span class="line">person.setName(<span class="string">&quot;Tom&quot;</span>);</span><br><span class="line">person.setAge(<span class="number">20</span>);</span><br><span class="line">Intent intent = <span class="keyword">new</span> Intent(FirstActivity.<span class="keyword">this</span>, SecondActivity.class);</span><br><span class="line">intent.putExtra(<span class="string">&quot;person_data&quot;</span>, person);</span><br><span class="line">startActivity(intent);</span><br></pre></td></tr></table></figure>
<p>接收时</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Person person = (Person) getIntent().getSerializableExtra(<span class="string">&quot;person_data&quot;</span>);</span><br></pre></td></tr></table></figure>
<h4 id="Parcelable方式">Parcelable方式<a class="header-anchor" href="#Parcelable方式"> ¶ </a></h4>
<p>实体类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Person</span> <span class="keyword">implements</span> <span class="title">Parcelable</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> age;</span><br><span class="line">    ...</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">describeContents</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// describeContents() 方法直接返回0就可以了</span></span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">writeToParcel</span><span class="params">(Parcel dest, <span class="keyword">int</span> flags)</span> </span>&#123;</span><br><span class="line">        dest.writeString(name);  <span class="comment">// 写出name</span></span><br><span class="line">        dest.writeInt(age);  <span class="comment">// 写出age</span></span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 而writeToParcel() 方法中我们需要调用Parcel的writeXxx() 方法，将Person 类中的字段一一写出。注意，字符串型数据就调用writeString()方法，整型数据就调用writeInt() 方法，以此类推。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> Parcelable.Creator&lt;Person&gt; CREATOR = <span class="keyword">new</span> Parcelable.</span><br><span class="line">        Creator&lt;Person&gt;() &#123;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> Person <span class="title">createFromParcel</span><span class="params">(Parcel source)</span> </span>&#123;</span><br><span class="line">            Person person = <span class="keyword">new</span> Person();</span><br><span class="line">            person.name = source.readString();  <span class="comment">// 读取name</span></span><br><span class="line">            person.age = source.readInt();  <span class="comment">// 读取age</span></span><br><span class="line">            <span class="keyword">return</span> person;</span><br><span class="line">            <span class="comment">// 读取存入，并返回对象</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="meta">@Override</span></span><br><span class="line">        <span class="keyword">public</span> Person[] newArray(<span class="keyword">int</span> size) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">new</span> Person[size];</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>传递方法相同</p>
<p>读取时</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Person person = (Person) getIntent().getParcelableExtra(<span class="string">&quot;person_data&quot;</span>);</span><br></pre></td></tr></table></figure>
<h3 id="自己的日志打印工具">自己的日志打印工具<a class="header-anchor" href="#自己的日志打印工具"> ¶ </a></h3>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LogUtil</span> </span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> VERBOSE = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DEBUG = <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> INFO = <span class="number">3</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> WARN = <span class="number">4</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> ERROR = <span class="number">5</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> NOTHING = <span class="number">6</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> level = VERBOSE;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">v</span><span class="params">(String tag, String msg)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (level &lt;= VERBOSE) &#123;</span><br><span class="line">            Log.v(tag, msg);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">d</span><span class="params">(String tag, String msg)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (level &lt;= DEBUG) &#123;</span><br><span class="line">            Log.d(tag, msg);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">i</span><span class="params">(String tag, String msg)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (level &lt;= INFO) &#123;</span><br><span class="line">            Log.i(tag, msg);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">w</span><span class="params">(String tag, String msg)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (level &lt;= WARN) &#123;</span><br><span class="line">            Log.w(tag, msg);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">e</span><span class="params">(String tag, String msg)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (level &lt;= ERROR) &#123;</span><br><span class="line">            Log.e(tag, msg);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>比如让level 等于VERBOSE 就可以把所有的日志都打印出来，让level 等于WARN 就可以只打印警告以上级别的日志，让level 等于NOTHING 就可以把所有日志都屏蔽掉。</p>
<h3 id="创建定时任务">创建定时任务<a class="header-anchor" href="#创建定时任务"> ¶ </a></h3>
<h4 id="Alarm机制">Alarm机制<a class="header-anchor" href="#Alarm机制"> ¶ </a></h4>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LongRunningService</span> <span class="keyword">extends</span> <span class="title">Service</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> IBinder <span class="title">onBind</span><span class="params">(Intent intent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">onStartCommand</span><span class="params">(Intent intent, <span class="keyword">int</span> flags, <span class="keyword">int</span> startId)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                <span class="comment">// 在这里执行具体的逻辑操作</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;).start();</span><br><span class="line">        <span class="comment">// 获得Alarm管理</span></span><br><span class="line">        AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);</span><br><span class="line">        <span class="keyword">int</span> anHour = <span class="number">60</span> * <span class="number">60</span> * <span class="number">1000</span>;  <span class="comment">// 这是一小时的毫秒数</span></span><br><span class="line">        <span class="comment">// 下次执行的时间</span></span><br><span class="line">        <span class="keyword">long</span> triggerAtTime = SystemClock.elapsedRealtime() + anHour;</span><br><span class="line">        Intent i = <span class="keyword">new</span> Intent(<span class="keyword">this</span>, LongRunningService.class);</span><br><span class="line">        <span class="comment">// 启动的意图</span></span><br><span class="line">        PendingIntent pi = PendingIntent.getService(<span class="keyword">this</span>, <span class="number">0</span>, i, <span class="number">0</span>);</span><br><span class="line">        <span class="comment">// 进行设置</span></span><br><span class="line">        manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">super</span>.onStartCommand(intent, flags, startId);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>要求时间准确，使用<code>setExact()</code>代替<code>set()</code></p>
<p>Doze模式：调用AlarmManager的setAndAllowWhileIdle() 或setExactAndAllowWhileIdle() 方法就能让定时任务即使在Doze模式下也能正常执行</p>
<h2 id="Android权限">Android权限<a class="header-anchor" href="#Android权限"> ¶ </a></h2>
<p><a target="_blank" rel="noopener" href="https://developer.android.google.cn/reference/android/Manifest.permission">Manifest.permission  | Android Developers (google.cn)</a></p>
<h3 id="常见权限">常见权限<a class="header-anchor" href="#常见权限"> ¶ </a></h3>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.INTERNET&quot;</span> /&gt;</span><span class="comment">&lt;!--    网络权限--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--    API28+还需在application节点中添加-9属性 --&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.ACCESS_NETWORK_STATE&quot;</span> /&gt;</span><span class="comment">&lt;!--    访问网络状态权限--&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.RECEIVE_BOOT_COMPLETED&quot;</span>/&gt;</span><span class="comment">&lt;!--    监听开机权限--&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.READ_EXTERNAL_STORAGE&quot;</span> /&gt;</span><span class="comment">&lt;!--    读外部存储权限--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">uses-permission</span> <span class="attr">android:name</span>=<span class="string">&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;</span>/&gt;</span><span class="comment">&lt;!--    写外部存储权限--&gt;</span></span><br><span class="line"><span class="comment">&lt;!--    从Android10开始,需要在application节点中添加android:requestLegacyExternalStorage=&quot;true&quot;属性--&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="运行时权限-2">运行时权限<a class="header-anchor" href="#运行时权限-2"> ¶ </a></h3>
<p><a href="#runtime_permission">动态申请运行时权限代码示例</a></p>
<table>
<thead>
<tr>
<th style="text-align:center">权限组名</th>
<th style="text-align:center">权限名</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">CALENDAR</td>
<td style="text-align:center">READ_CALENDAR<br>WRITE_CALENDAR</td>
</tr>
<tr>
<td style="text-align:center">CAMERA</td>
<td style="text-align:center">CAMERA</td>
</tr>
<tr>
<td style="text-align:center">CONTACTS</td>
<td style="text-align:center">READ_CONTACTS<br>WRITE_CONTACTS<br>GET_ACCOUNTS</td>
</tr>
<tr>
<td style="text-align:center">LOCATION</td>
<td style="text-align:center">ACCESS_FINE_LOCATION<br>ACCESS_COARSE_LOCATION</td>
</tr>
<tr>
<td style="text-align:center">MICROPHONE</td>
<td style="text-align:center">RECORD_AUDIO</td>
</tr>
<tr>
<td style="text-align:center">PHONE</td>
<td style="text-align:center">READ_PHONE_STATE<br>CALL_PHONE<br>READ_CALL_LOG<br>WRITE_CALL_LOG<br>ADD_VOICEMAIL<br>USE_SIP<br>PROCESS_OUTGOING_CALLS</td>
</tr>
<tr>
<td style="text-align:center">SENSORS</td>
<td style="text-align:center">BODY_SENSORS</td>
</tr>
<tr>
<td style="text-align:center">SMS</td>
<td style="text-align:center">SEND_SMS<br>RECEIVE_SMS<br>READ_SMS<br>RECEIVE_WAP_PUSH<br>RECEIVE_MMS</td>
</tr>
<tr>
<td style="text-align:center">STORAGE</td>
<td style="text-align:center">READ_EXTERNAL_STORAGE<br>WRITE_EXTERNAL_STORAGE</td>
</tr>
</tbody>
</table>
<h2 id="Git学习">Git学习<a class="header-anchor" href="#Git学习"> ¶ </a></h2>
<h3 id="Git高级用法">Git高级用法<a class="header-anchor" href="#Git高级用法"> ¶ </a></h3>
<h4 id="分支的用法">分支的用法<a class="header-anchor" href="#分支的用法"> ¶ </a></h4>
<ol>
<li>
<p>查看所有分支</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>创建分支</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch [name]</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>切换分支</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git checkout [name]</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>合并branch_a分支到master分支</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git checkout master</span><br><span class="line"></span><br><span class="line"><span class="comment"># 合并branch_a分支到当前分支</span></span><br><span class="line">git merge branch_a</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>删除分支</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch -D [name]</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h4 id="与远程协作">与远程协作<a class="header-anchor" href="#与远程协作"> ¶ </a></h4>
<ol>
<li>
<p>将远程代码下载到本地</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> [url]</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>将本地更改提交到远程</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push origin master</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>抓取远程到本地</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git fetch origin master</span><br></pre></td></tr></table></figure>
<p>同步下来的代码存放到<code>origin/master</code>分支上</p>
</li>
<li>
<p>查看远程版本库修改了什么（配合3）</p>
<p>查看后可以使用<code>git merge</code>合并分支到当前分支</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git diff origin/master</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>拉取最新代码并合并到本地（3,4的操作）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git pull origin master</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h1 id="零散知识块">零散知识块<a class="header-anchor" href="#零散知识块"> ¶ </a></h1>
<h2 id="Fragment">Fragment<a class="header-anchor" href="#Fragment"> ¶ </a></h2>
<h3 id="Fragment使用">Fragment使用<a class="header-anchor" href="#Fragment使用"> ¶ </a></h3>
<h4 id="Acitivity静态添加Fragment：">Acitivity静态添加Fragment：<a class="header-anchor" href="#Acitivity静态添加Fragment："> ¶ </a></h4>
<p>布局中添加<fragment>控件</fragment></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">fragment</span> <span class="attr">android:name</span>=<span class="string">&quot;&lt;Fragment全类名&gt;&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">android:layout_width</span>=<span class="string">&quot;&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">android:layout_height</span>=<span class="string">&quot;&quot;</span></span></span><br><span class="line"><span class="tag">          <span class="attr">android:id</span>=<span class="string">&quot;@+id/fragment_one&quot;</span></span></span><br><span class="line"><span class="tag">          /&gt;</span></span><br></pre></td></tr></table></figure>
<p>使用全类名直接指定相应fragment，activity就会自动嵌入该fragment</p>
<h4 id="Activity动态添加和管理Fragment：">Activity动态添加和管理Fragment：<a class="header-anchor" href="#Activity动态添加和管理Fragment："> ¶ </a></h4>
<ol>
<li>
<p>布局文件添加<code>&lt;FrameLayout&gt;</code>并设置ID属性</p>
</li>
<li>
<p>activity中动态替换Fragment代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">replaceFragment</span><span class="params">(Fragment fragment)</span></span>&#123;</span><br><span class="line">    <span class="comment">// 得到Fragment管理实例</span></span><br><span class="line">    FragmentManager fragmentManager = getSupportFragmentManager();</span><br><span class="line">    <span class="comment">// 开启一个事务</span></span><br><span class="line">    FragmentTransaction transaction = fragmentManager.beginTransaction();</span><br><span class="line">    <span class="comment">// 进行替换Fragment，参数1为控件ID，参数二为fragment实例（new得到）</span></span><br><span class="line">    transaction.replace(R.id.framelayout, fragment);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 根据需要；将fragment添加到返回栈，这样back返回的时候将是之前添加的fragment，直到所有fragment都弹出</span></span><br><span class="line">    <span class="comment">// transaction.addToBackStack(null);</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 提交事务</span></span><br><span class="line">    transaction.commit();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<h3 id="Fragment和Activity进行通信">Fragment和Activity进行通信<a class="header-anchor" href="#Fragment和Activity进行通信"> ¶ </a></h3>
<h4 id="使用bundle通信">使用bundle通信<a class="header-anchor" href="#使用bundle通信"> ¶ </a></h4>
<p>Activity给Fragment传递消息</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 新建一个Bundle对象</span></span><br><span class="line">Bundle bundle = <span class="keyword">new</span> Bundle();</span><br><span class="line"><span class="comment">// 放入相应数据键值对</span></span><br><span class="line">bundle.putString(<span class="string">&quot;message&quot;</span>,<span class="string">&quot;I&#x27;m from Activity&quot;</span>);</span><br><span class="line"><span class="comment">// new一个fragment实例</span></span><br><span class="line">MyFragment myFragment = <span class="keyword">new</span> MyFragment();</span><br><span class="line"><span class="comment">// 将参数传递进去</span></span><br><span class="line">myFragment.setArguments(bundle);</span><br></pre></td></tr></table></figure>
<p>Fragment接收的时候</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span></span>&#123;</span><br><span class="line">    <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">    <span class="comment">// 获取传递的信息</span></span><br><span class="line">    Bundle bundle = <span class="keyword">this</span>.getArguments();</span><br><span class="line">    <span class="comment">// 根据键获取传递信息中的某个值</span></span><br><span class="line">    String msg = bundle.getString(<span class="string">&quot;message&quot;</span>);</span><br><span class="line">    Log.d(TAG,<span class="string">&quot;From Acitvity: &quot;</span>+msg);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="使用Java接口进行通信">使用Java接口进行通信<a class="header-anchor" href="#使用Java接口进行通信"> ¶ </a></h4>
<p>为Fragment通信新建一个接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Fragment通信接口</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">IFragmentcallback</span> </span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 发送消息给Activity 方法</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">sendMsgToActivity</span><span class="params">(String msg)</span></span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 从Activity获取消息 方法</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function">String <span class="title">getMsgFromActivity</span><span class="params">(String msg)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>Acitvity代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">myFragment.setCallback(<span class="keyword">new</span> IFragmentcallback()&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">sendMsgToActivity</span><span class="params">(String msg)</span></span>&#123;</span><br><span class="line">        Log.d(TAG,<span class="string">&quot;From Fragment: &quot;</span>+msg);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function">String <span class="title">getMsgFromActivity</span><span class="params">(String msg)</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;Hi,I&#x27;m from Activity.&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p>Fragment代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> IFragmentcallback callback;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setCallback</span><span class="params">(IFragmentcallback callback)</span></span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.callback = callback;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="其他方案">其他方案<a class="header-anchor" href="#其他方案"> ¶ </a></h4>
<p>eventBus，LiveData…</p>
<h3 id="Fragment生命周期">Fragment生命周期<a class="header-anchor" href="#Fragment生命周期"> ¶ </a></h3>
<p><img src= "" data-lazy-src="/Development/android/Android_Development_Notes/1688279-0424d62f50035b43.png" alt="Fragment生命周期"></p>
<p>1.打开界面</p>
<p>onCreate() -&gt; onCreateView() -&gt;onActivityCreated() -&gt;onStart() -&gt;onResume()</p>
<p>2.按下主屏键</p>
<p>onPause() -&gt;onStop()</p>
<p>3.重新打开界面.</p>
<p>onStart() -&gt;onResume()</p>
<p>4.按后退键</p>
<p>onPause()- &gt;onStop()- &gt;onDestroyView()-&gt;onDestroy()- &gt;onDetach()</p>
<p>在fragment栈中被覆盖：onPause()- &gt;onStop()- &gt;onDestroyView()</p>
<p>fragment栈 重新显示：onCreateView() -&gt;onActivityCreated() -&gt;onStart() -&gt;onResume()</p>
<h3 id="ViewPager2与Fragment">ViewPager2与Fragment<a class="header-anchor" href="#ViewPager2与Fragment"> ¶ </a></h3>
<p><a target="_blank" rel="noopener" href="https://github.com/Forgo7ten/AndroidProjectPractice/tree/main/ViewPagerTest">AndroidProjectPractice/ViewPagerTest at main · Forgo7ten/AndroidProjectPractice (github.com)</a></p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">Forgo7ten</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://forgo7ten.github.io/Development/android/Android_Development_Notes/">https://forgo7ten.github.io/Development/android/Android_Development_Notes/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://Forgo7ten.github.io" target="_blank">Forgo7ten'blog</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Android/">Android</a></div><div class="post_share"><div class="social-share" data-image="http://forgo7ten.gitee.io/store/imgs/10.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/images/wechat.png" target="_blank"><img class="post-qr-code-img" src="/images/wechat.png" alt="wechat"/></a><div class="post-qr-code-desc">wechat</div></li><li class="reward-item"><a href="/images/alipay.jpg" target="_blank"><img class="post-qr-code-img" src="/images/alipay.jpg" alt="alipay"/></a><div class="post-qr-code-desc">alipay</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/Development/python/Python_Development_Notes/"><img class="prev-cover" src="http://forgo7ten.gitee.io/store/imgs/12.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">Python学习个人简记</div></div></a></div><div class="next-post pull-right"><a href="/AndroidReverse/2021/Initial_xposed_module_development/"><img class="next-cover" src="http://forgo7ten.gitee.io/store/imgs/11.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Xposed 模块开发一 环境搭建</div></div></a></div></nav><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="gitalk-container"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Android"><span class="toc-number">1.</span> <span class="toc-text">Android</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#Android%E5%9F%BA%E7%A1%80%E3%80%81%E9%A1%B9%E7%9B%AE%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84"><span class="toc-number">1.1.</span> <span class="toc-text">Android基础、项目目录结构</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%A1%B9%E7%9B%AE%E7%BB%93%E6%9E%84"><span class="toc-number">1.1.1.</span> <span class="toc-text">项目结构</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Project"><span class="toc-number">1.1.1.1.</span> <span class="toc-text">Project</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#app%E7%9B%AE%E5%BD%95"><span class="toc-number">1.1.1.2.</span> <span class="toc-text">app目录</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#build-gradle%E6%96%87%E4%BB%B6"><span class="toc-number">1.1.1.3.</span> <span class="toc-text">build.gradle文件</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#%E6%9C%80%E5%A4%96%E5%B1%82%E7%9B%AE%E5%BD%95build-gradle"><span class="toc-number">1.1.1.3.0.1.</span> <span class="toc-text">最外层目录build.gradle</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#app%E5%86%85%E9%83%A8build-gradle"><span class="toc-number">1.1.1.3.0.2.</span> <span class="toc-text">app内部build.gradle</span></a></li></ol></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#res%E8%B5%84%E6%BA%90%E7%9B%AE%E5%BD%95"><span class="toc-number">1.1.1.4.</span> <span class="toc-text">res资源目录</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#string-xml%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%B5%84%E6%BA%90"><span class="toc-number">1.1.1.4.1.</span> <span class="toc-text">string.xml字符串资源</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%97%A5%E5%BF%97%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8"><span class="toc-number">1.1.2.</span> <span class="toc-text">日志工具使用</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Android%E7%9A%84%E6%97%A5%E5%BF%97%E5%B7%A5%E5%85%B7Log"><span class="toc-number">1.1.2.1.</span> <span class="toc-text">使用Android的日志工具Log</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Android-UI%E6%8E%A7%E4%BB%B6"><span class="toc-number">1.2.</span> <span class="toc-text">Android UI控件</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#AlertDialog"><span class="toc-number">1.2.1.</span> <span class="toc-text">AlertDialog</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ProgressDialog"><span class="toc-number">1.2.2.</span> <span class="toc-text">ProgressDialog</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%8F%9C%E5%8D%95Menu"><span class="toc-number">1.2.3.</span> <span class="toc-text">菜单Menu</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-%E6%96%B0%E5%BB%BA%E8%8F%9C%E5%8D%95Menu%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6"><span class="toc-number">1.2.3.1.</span> <span class="toc-text">1. 新建菜单Menu资源文件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-Activity%E9%87%8D%E5%86%99onCreateOptionsMenu-%E6%96%B9%E6%B3%95"><span class="toc-number">1.2.3.2.</span> <span class="toc-text">2. Activity重写onCreateOptionsMenu()方法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-%E9%87%8D%E5%86%99onOptionsItemSelected-%E6%96%B9%E6%B3%95"><span class="toc-number">1.2.3.3.</span> <span class="toc-text">3. 重写onOptionsItemSelected()方法</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#WebView%E7%94%A8%E6%B3%95"><span class="toc-number">1.2.4.</span> <span class="toc-text">WebView用法</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ListView"><span class="toc-number">1.2.5.</span> <span class="toc-text">ListView</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-%E7%BC%96%E5%86%99%E5%AD%90%E5%85%83%E7%B4%A0%E7%95%8C%E9%9D%A2"><span class="toc-number">1.2.5.1.</span> <span class="toc-text">1. 编写子元素界面</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-%E7%BC%96%E5%86%99Adapter"><span class="toc-number">1.2.5.2.</span> <span class="toc-text">2. 编写Adapter</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-%E7%BB%99listView%E5%AF%B9%E8%B1%A1%E8%AE%BE%E7%BD%AEadapter"><span class="toc-number">1.2.5.3.</span> <span class="toc-text">3. 给listView对象设置adapter</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#RecyclerView%E6%BB%9A%E5%8A%A8%E6%8E%A7%E4%BB%B6"><span class="toc-number">1.2.6.</span> <span class="toc-text">RecyclerView滚动控件</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96"><span class="toc-number">1.2.6.0.1.</span> <span class="toc-text">添加依赖</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Layout%E5%BC%95%E7%94%A8"><span class="toc-number">1.2.6.0.2.</span> <span class="toc-text">Layout引用</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Adapter%E8%87%AA%E5%AE%9A%E4%B9%89%E9%80%82%E9%85%8D%E5%99%A8"><span class="toc-number">1.2.6.0.3.</span> <span class="toc-text">Adapter自定义适配器</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%B0%83%E7%94%A8%E7%94%9F%E6%88%90"><span class="toc-number">1.2.6.0.4.</span> <span class="toc-text">调用生成</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%82%B9%E5%87%BB%E4%BA%8B%E4%BB%B6"><span class="toc-number">1.2.6.0.5.</span> <span class="toc-text">点击事件</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B8%83%E5%B1%80"><span class="toc-number">1.2.7.</span> <span class="toc-text">布局</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#LinearLayout%E7%BA%BF%E6%80%A7%E5%B8%83%E5%B1%80"><span class="toc-number">1.2.7.1.</span> <span class="toc-text">LinearLayout线性布局</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RelativeLayout%E7%9B%B8%E5%AF%B9%E5%B8%83%E5%B1%80"><span class="toc-number">1.2.7.2.</span> <span class="toc-text">RelativeLayout相对布局</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#FrameLayout%E5%B8%A7%E5%B8%83%E5%B1%80"><span class="toc-number">1.2.7.3.</span> <span class="toc-text">FrameLayout帧布局</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%95%E5%85%A5%E5%B8%83%E5%B1%80"><span class="toc-number">1.2.7.4.</span> <span class="toc-text">引入布局</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B8%83%E5%B1%80"><span class="toc-number">1.2.7.5.</span> <span class="toc-text">自定义布局</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%B6%E4%BD%9C9-Patch%E5%9B%BE%E7%89%87"><span class="toc-number">1.2.8.</span> <span class="toc-text">制作9-Patch图片</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Android-%E8%B5%84%E6%BA%90"><span class="toc-number">1.3.</span> <span class="toc-text">Android 资源</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#res%E7%9B%AE%E5%BD%95"><span class="toc-number">1.3.1.</span> <span class="toc-text">res目录</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#res-values"><span class="toc-number">1.3.1.1.</span> <span class="toc-text">res&#x2F;values</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#res-values-String-xml"><span class="toc-number">1.3.1.1.1.</span> <span class="toc-text">res&#x2F;values&#x2F;String.xml</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-values-colors-xml"><span class="toc-number">1.3.1.1.2.</span> <span class="toc-text">res&#x2F;values&#x2F;colors.xml</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-values-dimens-xml"><span class="toc-number">1.3.1.1.3.</span> <span class="toc-text">res&#x2F;values&#x2F;dimens.xml</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-values-array-xml"><span class="toc-number">1.3.1.1.4.</span> <span class="toc-text">res&#x2F;values&#x2F;array.xml</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-values-style"><span class="toc-number">1.3.1.1.5.</span> <span class="toc-text">res&#x2F;values&#x2F;style</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-values-theme"><span class="toc-number">1.3.1.1.6.</span> <span class="toc-text">res&#x2F;values&#x2F;theme</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-mipmap"><span class="toc-number">1.3.1.1.7.</span> <span class="toc-text">res&#x2F;mipmap&#x2F;</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-drawable"><span class="toc-number">1.3.1.1.8.</span> <span class="toc-text">res&#x2F;drawable&#x2F;</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-xml"><span class="toc-number">1.3.1.1.9.</span> <span class="toc-text">res&#x2F;xml&#x2F;</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#res-raw"><span class="toc-number">1.3.1.1.10.</span> <span class="toc-text">res&#x2F;raw&#x2F;</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Assets%E7%9B%AE%E5%BD%95"><span class="toc-number">1.3.2.</span> <span class="toc-text">Assets目录</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Activity%E6%B4%BB%E5%8A%A8"><span class="toc-number">1.4.</span> <span class="toc-text">Activity活动</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B4%BB%E5%8A%A8%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95"><span class="toc-number">1.4.1.</span> <span class="toc-text">活动基本用法</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B3%A8%E5%86%8C%E6%B4%BB%E5%8A%A8"><span class="toc-number">1.4.1.1.</span> <span class="toc-text">注册活动</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%94%80%E6%AF%81%E6%B4%BB%E5%8A%A8"><span class="toc-number">1.4.1.2.</span> <span class="toc-text">销毁活动</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Intent"><span class="toc-number">1.4.2.</span> <span class="toc-text">使用Intent</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%98%BE%E5%BC%8FIntent"><span class="toc-number">1.4.2.1.</span> <span class="toc-text">显式Intent</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9A%90%E5%BC%8FIntent"><span class="toc-number">1.4.2.2.</span> <span class="toc-text">隐式Intent</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%90%91%E4%B8%8B%E4%B8%80%E4%B8%AA%E6%B4%BB%E5%8A%A8%E4%BC%A0%E9%80%92%E6%95%B0%E6%8D%AE"><span class="toc-number">1.4.2.3.</span> <span class="toc-text">向下一个活动传递数据</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%BF%94%E5%9B%9E%E6%95%B0%E6%8D%AE%E7%BB%99%E4%B8%8A%E4%B8%80%E4%B8%AA%E6%B4%BB%E5%8A%A8"><span class="toc-number">1.4.2.4.</span> <span class="toc-text">返回数据给上一个活动</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Activity%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">1.4.3.</span> <span class="toc-text">Activity生命周期</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%BF%94%E5%9B%9E%E6%A0%88"><span class="toc-number">1.4.3.1.</span> <span class="toc-text">返回栈</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B4%BB%E5%8A%A8%E7%8A%B6%E6%80%81"><span class="toc-number">1.4.3.2.</span> <span class="toc-text">活动状态</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B4%BB%E5%8A%A8%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">1.4.3.3.</span> <span class="toc-text">活动的生命周期</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B4%BB%E5%8A%A8%E8%A2%AB%E5%9B%9E%E6%94%B6%E4%BA%86%E6%80%8E%E4%B9%88%E5%8A%9E"><span class="toc-number">1.4.3.4.</span> <span class="toc-text">活动被回收了怎么办</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B4%BB%E5%8A%A8%E7%9A%84%E5%90%AF%E5%8A%A8%E6%A8%A1%E5%BC%8F"><span class="toc-number">1.4.4.</span> <span class="toc-text">活动的启动模式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%B7%A8%E5%BA%94%E7%94%A8%E5%90%AF%E5%8A%A8Activity"><span class="toc-number">1.4.4.1.</span> <span class="toc-text">跨应用启动Activity</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B4%BB%E5%8A%A8%E7%AE%A1%E7%90%86"><span class="toc-number">1.4.5.</span> <span class="toc-text">活动管理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BA%86%E8%A7%A3%E5%BD%93%E5%89%8D%E7%95%8C%E9%9D%A2%E5%AF%B9%E5%BA%94%E6%B4%BB%E5%8A%A8"><span class="toc-number">1.4.5.1.</span> <span class="toc-text">了解当前界面对应活动</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B4%BB%E5%8A%A8%E7%AE%A1%E7%90%86%E5%99%A8"><span class="toc-number">1.4.5.2.</span> <span class="toc-text">活动管理器</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%80%80%E5%87%BA%E7%A8%8B%E5%BA%8F"><span class="toc-number">1.4.5.2.1.</span> <span class="toc-text">退出程序</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%90%AF%E5%8A%A8Activity"><span class="toc-number">1.4.5.3.</span> <span class="toc-text">启动Activity</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B9%BF%E6%92%AD%E6%8E%A5%E6%94%B6%E8%80%85BroadcastReceiver"><span class="toc-number">1.5.</span> <span class="toc-text">广播接收者BroadcastReceiver</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B9%BF%E6%92%AD%E6%9C%BA%E5%88%B6%E7%AE%80%E4%BB%8B"><span class="toc-number">1.5.1.</span> <span class="toc-text">广播机制简介</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8E%A5%E6%94%B6%E7%B3%BB%E7%BB%9F%E5%B9%BF%E6%92%AD"><span class="toc-number">1.5.2.</span> <span class="toc-text">接收系统广播</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8A%A8%E6%80%81%E6%B3%A8%E5%86%8C%E7%9B%91%E5%90%AC%E7%BD%91%E7%BB%9C%E5%8F%98%E5%8C%96"><span class="toc-number">1.5.2.1.</span> <span class="toc-text">动态注册监听网络变化</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%9D%99%E6%80%81%E6%B3%A8%E5%86%8C%E5%AE%9E%E7%8E%B0%E5%BC%80%E6%9C%BA%E5%90%AF%E5%8A%A8%E6%8F%90%E9%86%92"><span class="toc-number">1.5.2.2.</span> <span class="toc-text">静态注册实现开机启动提醒</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8F%91%E9%80%81%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B9%BF%E6%92%AD"><span class="toc-number">1.5.2.3.</span> <span class="toc-text">发送自定义广播</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8F%91%E9%80%81%E6%A0%87%E5%87%86%E5%B9%BF%E6%92%AD"><span class="toc-number">1.5.2.3.1.</span> <span class="toc-text">发送标准广播</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E8%87%AA%E5%B7%B1%E7%9A%84%E5%B9%BF%E6%92%AD%E6%8E%A5%E6%94%B6%E5%99%A8"><span class="toc-number">1.5.2.3.1.1.</span> <span class="toc-text">定义一个自己的广播接收器</span></a></li></ol></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8F%91%E9%80%81%E6%9C%89%E5%BA%8F%E5%B9%BF%E6%92%AD"><span class="toc-number">1.5.2.3.2.</span> <span class="toc-text">发送有序广播</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E6%9C%AC%E5%9C%B0%E5%B9%BF%E6%92%AD"><span class="toc-number">1.5.3.</span> <span class="toc-text">使用本地广播</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E5%B9%BF%E6%92%AD%E6%9D%A5%E5%AE%9E%E7%8E%B0%E5%BC%BA%E5%88%B6%E4%B8%8B%E7%BA%BF%E5%8A%9F%E8%83%BD"><span class="toc-number">1.5.4.</span> <span class="toc-text">使用广播来实现强制下线功能</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8-%E6%8C%81%E4%B9%85%E5%8C%96%E6%8A%80%E6%9C%AF"><span class="toc-number">1.6.</span> <span class="toc-text">数据存储 持久化技术</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8"><span class="toc-number">1.6.1.</span> <span class="toc-text">文件存储</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#SD%E5%8D%A1%E6%96%87%E4%BB%B6%E8%AF%BB%E5%86%99"><span class="toc-number">1.6.2.</span> <span class="toc-text">SD卡文件读写</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#SharedPreferences%E5%AD%98%E5%82%A8"><span class="toc-number">1.6.3.</span> <span class="toc-text">SharedPreferences存储</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%B0%86%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8%E5%88%B0SharedPreferences%E4%B8%AD"><span class="toc-number">1.6.3.1.</span> <span class="toc-text">将数据存储到SharedPreferences中</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96SharedPreferences%E5%AF%B9%E8%B1%A1"><span class="toc-number">1.6.3.1.1.</span> <span class="toc-text">获取SharedPreferences对象</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E5%AF%B9%E8%B1%A1%E8%BF%9B%E8%A1%8C%E5%AD%98%E5%82%A8"><span class="toc-number">1.6.3.1.2.</span> <span class="toc-text">使用对象进行存储</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BB%8ESharedPreferences%E4%B8%AD%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.3.2.</span> <span class="toc-text">从SharedPreferences中读取数据</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#SQLite%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AD%98%E5%82%A8"><span class="toc-number">1.6.4.</span> <span class="toc-text">SQLite数据库存储</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E6%95%B0%E6%8D%AE%E5%BA%93"><span class="toc-number">1.6.4.1.</span> <span class="toc-text">创建数据库</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#SQLiteOpenHelper%E6%9E%84%E9%80%A0%E6%96%B9%E6%B3%95"><span class="toc-number">1.6.4.1.1.</span> <span class="toc-text">SQLiteOpenHelper构造方法</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8SQLiteOpenHelper%E5%AE%9E%E7%8E%B0%E7%B1%BB"><span class="toc-number">1.6.4.1.2.</span> <span class="toc-text">使用SQLiteOpenHelper实现类</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AF%B9%E8%B1%A1"><span class="toc-number">1.6.4.2.</span> <span class="toc-text">获取数据库对象</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B7%BB%E5%8A%A0%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.4.3.</span> <span class="toc-text">添加数据</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9B%B4%E6%96%B0%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.4.4.</span> <span class="toc-text">更新数据</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%A0%E9%99%A4%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.4.5.</span> <span class="toc-text">删除数据</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.4.6.</span> <span class="toc-text">查询数据</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#Cursor%E7%B1%BB%E6%96%B9%E6%B3%95"><span class="toc-number">1.6.4.6.1.</span> <span class="toc-text">Cursor类方法</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8SQL%E6%93%8D%E4%BD%9C%E6%95%B0%E6%8D%AE%E5%BA%93"><span class="toc-number">1.6.4.7.</span> <span class="toc-text">使用SQL操作数据库</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8LitePal%E6%93%8D%E4%BD%9C%E6%95%B0%E6%8D%AE%E5%BA%93"><span class="toc-number">1.6.5.</span> <span class="toc-text">使用LitePal操作数据库</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%85%8D%E7%BD%AELitePal"><span class="toc-number">1.6.5.1.</span> <span class="toc-text">配置LitePal</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-%E6%B7%BB%E5%8A%A0LitePal%E4%BE%9D%E8%B5%96"><span class="toc-number">1.6.5.1.1.</span> <span class="toc-text">1. 添加LitePal依赖</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-%E9%85%8D%E7%BD%AElitepal-xml%E6%96%87%E4%BB%B6"><span class="toc-number">1.6.5.1.2.</span> <span class="toc-text">2. 配置litepal.xml文件</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-%E9%85%8D%E7%BD%AELitePalApplication"><span class="toc-number">1.6.5.1.3.</span> <span class="toc-text">3. 配置LitePalApplication</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E5%92%8C%E5%8D%87%E7%BA%A7%E6%95%B0%E6%8D%AE%E5%BA%93"><span class="toc-number">1.6.5.2.</span> <span class="toc-text">创建和升级数据库</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8LitePal%E6%B7%BB%E5%8A%A0%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.5.3.</span> <span class="toc-text">使用LitePal添加数据</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8LitePal%E6%9B%B4%E6%96%B0%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.5.4.</span> <span class="toc-text">使用LitePal更新数据</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8LitePal%E5%88%A0%E9%99%A4%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.5.5.</span> <span class="toc-text">使用LitePal删除数据</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8LitePal%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE"><span class="toc-number">1.6.5.6.</span> <span class="toc-text">使用LitePal查询数据</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#ContentProvider%E5%86%85%E5%AE%B9%E6%8F%90%E4%BE%9B%E8%80%85"><span class="toc-number">1.7.</span> <span class="toc-text">ContentProvider内容提供者</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E6%9D%83%E9%99%90"><span class="toc-number">1.7.1.</span> <span class="toc-text">运行时权限</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E6%9D%83%E9%99%90%E6%9C%BA%E5%88%B6"><span class="toc-number">1.7.1.1.</span> <span class="toc-text">运行时权限机制</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%A8%8B%E5%BA%8F%E8%BF%90%E8%A1%8C%E6%97%B6%E7%94%B3%E8%AF%B7%E6%9D%83%E9%99%90"><span class="toc-number">1.7.2.</span> <span class="toc-text">程序运行时申请权限</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Android6-0%E4%B9%8B%E5%89%8D"><span class="toc-number">1.7.2.1.</span> <span class="toc-text">Android6.0之前</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Android6-0%E4%BB%A5%E5%90%8E%EF%BC%8C%E5%8A%A8%E6%80%81%E7%94%B3%E8%AF%B7%E6%9D%83%E9%99%90"><span class="toc-number">1.7.2.2.</span> <span class="toc-text">Android6.0以后，动态申请权限</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AE%BF%E9%97%AE%E5%85%B6%E4%BB%96%E7%A8%8B%E5%BA%8F%E4%B8%AD%E6%95%B0%E6%8D%AE"><span class="toc-number">1.7.3.</span> <span class="toc-text">访问其他程序中数据</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#ContentResolver%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95"><span class="toc-number">1.7.3.1.</span> <span class="toc-text">ContentResolver的基本用法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%AF%BB%E5%8F%96%E7%B3%BB%E7%BB%9F%E8%81%94%E7%B3%BB%E4%BA%BA"><span class="toc-number">1.7.3.2.</span> <span class="toc-text">读取系统联系人</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84%E5%86%85%E5%AE%B9%E6%8F%90%E4%BE%9B%E5%99%A8"><span class="toc-number">1.7.4.</span> <span class="toc-text">创建自己的内容提供器</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E5%86%85%E5%AE%B9%E6%8F%90%E4%BE%9B%E5%99%A8%E7%9A%84%E6%AD%A5%E9%AA%A4"><span class="toc-number">1.7.4.1.</span> <span class="toc-text">创建内容提供器的步骤</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AE%9E%E7%8E%B0%E8%B7%A8%E7%A8%8B%E5%BA%8F%E6%95%B0%E6%8D%AE%E5%85%B1%E4%BA%AB"><span class="toc-number">1.7.4.2.</span> <span class="toc-text">实现跨程序数据共享</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E7%BD%91%E7%BB%9C%E6%8A%80%E6%9C%AF"><span class="toc-number">1.8.</span> <span class="toc-text">使用网络技术</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Http%E8%AE%BF%E9%97%AE%E7%BD%91%E7%BB%9C"><span class="toc-number">1.8.1.</span> <span class="toc-text">使用Http访问网络</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8HttpURLConnection"><span class="toc-number">1.8.1.1.</span> <span class="toc-text">使用HttpURLConnection</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8OkHttp"><span class="toc-number">1.8.1.2.</span> <span class="toc-text">使用OkHttp</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%AF%BC%E5%85%A5%E4%BE%9D%E8%B5%96"><span class="toc-number">1.8.1.2.1.</span> <span class="toc-text">导入依赖</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8-2"><span class="toc-number">1.8.1.2.2.</span> <span class="toc-text">使用</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#get%E5%90%8C%E6%AD%A5%E8%AF%B7%E6%B1%82"><span class="toc-number">1.8.1.2.2.1.</span> <span class="toc-text">get同步请求</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#get%E5%BC%82%E6%AD%A5%E8%AF%B7%E6%B1%82"><span class="toc-number">1.8.1.2.2.2.</span> <span class="toc-text">get异步请求</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5post%EF%BC%9A%E5%8F%91%E9%80%81%E6%96%87%E6%9C%AC"><span class="toc-number">1.8.1.2.2.3.</span> <span class="toc-text">异步post：发送文本</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5post%EF%BC%9A%E5%8F%91%E9%80%81%E8%A1%A8%E5%8D%95"><span class="toc-number">1.8.1.2.2.4.</span> <span class="toc-text">异步post：发送表单</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#post%E6%9C%AC%E5%9C%B0%E9%80%89%E6%8B%A9%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0"><span class="toc-number">1.8.1.2.2.5.</span> <span class="toc-text">post本地选择文件上传</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#post%E4%B8%8B%E8%BD%BD%E8%BF%9C%E7%AB%AF"><span class="toc-number">1.8.1.2.2.6.</span> <span class="toc-text">post下载远端</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%A7%A3%E6%9E%90XML%E6%A0%BC%E5%BC%8F%E6%95%B0%E6%8D%AE"><span class="toc-number">1.8.2.</span> <span class="toc-text">解析XML格式数据</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Pull%E8%A7%A3%E6%9E%90%E6%96%B9%E5%BC%8F"><span class="toc-number">1.8.2.1.</span> <span class="toc-text">Pull解析方式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#SAX%E8%A7%A3%E6%9E%90%E6%96%B9%E5%BC%8F"><span class="toc-number">1.8.2.2.</span> <span class="toc-text">SAX解析方式</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%A7%A3%E6%9E%90JSON%E6%A0%BC%E5%BC%8F%E6%95%B0%E6%8D%AE"><span class="toc-number">1.8.3.</span> <span class="toc-text">解析JSON格式数据</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8JSONObject"><span class="toc-number">1.8.3.1.</span> <span class="toc-text">使用JSONObject</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%BD%AC%E6%88%90Json%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="toc-number">1.8.3.1.1.</span> <span class="toc-text">转成Json字符串</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%AF%BB%E5%8F%96JSON%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="toc-number">1.8.3.1.2.</span> <span class="toc-text">读取JSON字符串</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Gson"><span class="toc-number">1.8.3.2.</span> <span class="toc-text">使用Gson</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96-2"><span class="toc-number">1.8.3.2.1.</span> <span class="toc-text">添加依赖</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8-3"><span class="toc-number">1.8.3.2.2.</span> <span class="toc-text">使用</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#Builder%E8%AE%BE%E7%BD%AEGson%E5%B1%9E%E6%80%A7"><span class="toc-number">1.8.3.2.2.1.</span> <span class="toc-text">Builder设置Gson属性</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E8%BD%ACjson%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="toc-number">1.8.3.2.2.2.</span> <span class="toc-text">对象转json字符串</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9B%B4%E6%8E%A5%E8%A7%A3%E6%9E%90%E5%AF%B9%E8%B1%A1"><span class="toc-number">1.8.3.2.2.3.</span> <span class="toc-text">字符串直接解析对象</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#Json%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%BA%E5%AF%B9%E8%B1%A1%E6%95%B0%E7%BB%84"><span class="toc-number">1.8.3.2.2.4.</span> <span class="toc-text">Json字符串为对象数组</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E5%AE%9E%E8%B7%B5"><span class="toc-number">1.8.4.</span> <span class="toc-text">网络编程实践</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Java%E5%9B%9E%E8%B0%83%E6%9C%BA%E5%88%B6"><span class="toc-number">1.8.4.1.</span> <span class="toc-text">Java回调机制</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AAHttpCallbackListener%E6%8E%A5%E5%8F%A3"><span class="toc-number">1.8.4.1.1.</span> <span class="toc-text">1. 定义一个HttpCallbackListener接口</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-%E4%BF%AE%E6%94%B9%E5%8E%9FHttpUtil%E7%B1%BB"><span class="toc-number">1.8.4.1.2.</span> <span class="toc-text">2.修改原HttpUtil类</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8OkHttp-2"><span class="toc-number">1.8.4.2.</span> <span class="toc-text">使用OkHttp</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Service%E6%9C%8D%E5%8A%A1"><span class="toc-number">1.9.</span> <span class="toc-text">Service服务</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Android%E5%A4%9A%E7%BA%BF%E7%A8%8B"><span class="toc-number">1.9.1.</span> <span class="toc-text">Android多线程</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5%E6%B6%88%E6%81%AF%E6%9B%B4%E6%96%B0UI"><span class="toc-number">1.9.1.1.</span> <span class="toc-text">异步消息更新UI</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5%E6%B6%88%E6%81%AF%E5%A4%84%E7%90%86%E6%9C%BA%E5%88%B6"><span class="toc-number">1.9.1.1.1.</span> <span class="toc-text">异步消息处理机制</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8AsyncTask%E7%B1%BB"><span class="toc-number">1.9.1.2.</span> <span class="toc-text">使用AsyncTask类</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Service%E6%9C%8D%E5%8A%A1-2"><span class="toc-number">1.9.2.</span> <span class="toc-text">Service服务</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AE%9A%E4%B9%89%E4%B8%80%E4%B8%AA%E6%9C%8D%E5%8A%A1"><span class="toc-number">1.9.2.1.</span> <span class="toc-text">定义一个服务</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%90%AF%E5%8A%A8%E5%92%8C%E5%81%9C%E6%AD%A2%E6%9C%8D%E5%8A%A1"><span class="toc-number">1.9.2.2.</span> <span class="toc-text">启动和停止服务</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B4%BB%E5%8A%A8%E5%92%8C%E6%9C%8D%E5%8A%A1%E7%BB%91%E5%AE%9A"><span class="toc-number">1.9.2.3.</span> <span class="toc-text">活动和服务绑定</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9C%8D%E5%8A%A1Service%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">1.9.2.4.</span> <span class="toc-text">服务Service的生命周期</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%9B%B4%E5%A4%9A%E6%8A%80%E5%B7%A7"><span class="toc-number">1.9.3.</span> <span class="toc-text">服务的更多技巧</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E5%89%8D%E5%8F%B0%E6%9C%8D%E5%8A%A1"><span class="toc-number">1.9.4.</span> <span class="toc-text">使用前台服务</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8IntentService"><span class="toc-number">1.9.4.1.</span> <span class="toc-text">使用IntentService</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8JobService"><span class="toc-number">1.9.4.2.</span> <span class="toc-text">使用JobService</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5%E2%80%94%E2%80%94%E5%AE%8C%E6%95%B4%E7%89%88%E7%9A%84%E4%B8%8B%E8%BD%BD%E7%A4%BA%E4%BE%8B"><span class="toc-number">1.9.5.</span> <span class="toc-text">服务的最佳实践——完整版的下载示例</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9F%BA%E4%BA%8E%E4%BD%8D%E7%BD%AE%E7%9A%84%E6%9C%8D%E5%8A%A1"><span class="toc-number">1.10.</span> <span class="toc-text">基于位置的服务</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BEAPI"><span class="toc-number">1.10.1.</span> <span class="toc-text">百度地图API</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%94%B3%E8%AF%B7API"><span class="toc-number">1.10.1.1.</span> <span class="toc-text">申请API</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96%E5%BC%80%E5%8F%91%E7%89%88-debug-SHA1"><span class="toc-number">1.10.1.1.1.</span> <span class="toc-text">获取开发版(debug) SHA1</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96%E5%8F%91%E5%B8%83%E6%9D%BF-release-SHA1"><span class="toc-number">1.10.1.1.2.</span> <span class="toc-text">获取发布板(release) SHA1</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8C%85%E5%90%8D%E6%AD%A3%E5%B8%B8%E8%AE%BE%E7%BD%AE"><span class="toc-number">1.10.1.1.3.</span> <span class="toc-text">包名正常设置</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%82%B9%E5%87%BB%E6%8F%90%E4%BA%A4"><span class="toc-number">1.10.1.1.4.</span> <span class="toc-text">点击提交</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8F%AF%E5%A4%8D%E5%88%B6key%EF%BC%8C%E6%88%96%E8%80%85-%E8%AE%BE%E7%BD%AE-%E4%BF%AE%E6%94%B9%E4%B8%8A%E8%BF%B0%E9%85%8D%E7%BD%AE"><span class="toc-number">1.10.1.1.5.</span> <span class="toc-text">可复制key，或者[设置]修改上述配置</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E7%99%BE%E5%BA%A6%E5%AE%9A%E4%BD%8D"><span class="toc-number">1.10.2.</span> <span class="toc-text">使用百度定位</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E4%B8%8B%E8%BD%BD-%E9%85%8D%E7%BD%AESDK"><span class="toc-number">1.10.2.0.1.</span> <span class="toc-text">下载&amp;配置SDK</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#%E4%B8%8B%E8%BD%BDSDK"><span class="toc-number">1.10.2.0.1.1.</span> <span class="toc-text">下载SDK</span></a></li><li class="toc-item toc-level-6"><a class="toc-link" href="#%E9%85%8D%E7%BD%AESDK"><span class="toc-number">1.10.2.0.1.2.</span> <span class="toc-text">配置SDK</span></a></li></ol></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE"><span class="toc-number">1.10.2.0.2.</span> <span class="toc-text">项目配置</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#AndroidManifest%E9%85%8D%E7%BD%AE"><span class="toc-number">1.10.2.0.2.1.</span> <span class="toc-text">AndroidManifest配置</span></a></li></ol></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E4%BB%A3%E7%A0%81"><span class="toc-number">1.10.2.0.3.</span> <span class="toc-text">代码</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%AE%9E%E6%97%B6%E6%9B%B4%E6%96%B0%E4%BD%8D%E7%BD%AE"><span class="toc-number">1.10.2.0.4.</span> <span class="toc-text">实时更新位置</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%80%89%E6%8B%A9%E5%AE%9A%E4%BD%8D%E6%A8%A1%E5%BC%8F"><span class="toc-number">1.10.2.1.</span> <span class="toc-text">选择定位模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%98%BE%E7%A4%BA%E4%BD%8D%E7%BD%AE%E7%9B%B8%E5%85%B3%E4%BF%A1%E6%81%AF"><span class="toc-number">1.10.2.2.</span> <span class="toc-text">显示位置相关信息</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE"><span class="toc-number">1.10.3.</span> <span class="toc-text">使用百度地图</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AE%9A%E4%BD%8D%E5%88%B0%E5%BD%93%E5%89%8D%E4%BD%8D%E7%BD%AE"><span class="toc-number">1.10.3.1.</span> <span class="toc-text">定位到当前位置</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%98%BE%E7%A4%BA%E6%89%80%E5%9C%A8%E4%BD%8D%E7%BD%AE%E5%85%89%E6%A0%87"><span class="toc-number">1.10.3.2.</span> <span class="toc-text">显示所在位置光标</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%9C%80%E4%BD%B3%E7%9A%84UI%E4%BD%93%E9%AA%8C%E2%80%94%E2%80%94MaterialDesign%E5%AE%9E%E6%88%98"><span class="toc-number">1.11.</span> <span class="toc-text">最佳的UI体验——MaterialDesign实战</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Toolbar"><span class="toc-number">1.11.1.</span> <span class="toc-text">Toolbar</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%A7%E7%BB%AD%E8%BF%9B%E9%98%B6%E2%80%94%E5%BA%94%E8%AF%A5%E6%8E%8C%E6%8F%A1%E7%9A%84%E9%AB%98%E7%BA%A7%E6%8A%80%E5%B7%A7"><span class="toc-number">1.12.</span> <span class="toc-text">继续进阶—应该掌握的高级技巧</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%85%A8%E5%B1%80%E8%8E%B7%E5%8F%96Context%E6%8A%80%E5%B7%A7"><span class="toc-number">1.12.1.</span> <span class="toc-text">全局获取Context技巧</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Intent%E4%BC%A0%E9%80%92%E5%AF%B9%E8%B1%A1"><span class="toc-number">1.12.2.</span> <span class="toc-text">使用Intent传递对象</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Serializable%E6%96%B9%E5%BC%8F"><span class="toc-number">1.12.2.1.</span> <span class="toc-text">Serializable方式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Parcelable%E6%96%B9%E5%BC%8F"><span class="toc-number">1.12.2.2.</span> <span class="toc-text">Parcelable方式</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%87%AA%E5%B7%B1%E7%9A%84%E6%97%A5%E5%BF%97%E6%89%93%E5%8D%B0%E5%B7%A5%E5%85%B7"><span class="toc-number">1.12.3.</span> <span class="toc-text">自己的日志打印工具</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1"><span class="toc-number">1.12.4.</span> <span class="toc-text">创建定时任务</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Alarm%E6%9C%BA%E5%88%B6"><span class="toc-number">1.12.4.1.</span> <span class="toc-text">Alarm机制</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Android%E6%9D%83%E9%99%90"><span class="toc-number">1.13.</span> <span class="toc-text">Android权限</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B8%B8%E8%A7%81%E6%9D%83%E9%99%90"><span class="toc-number">1.13.1.</span> <span class="toc-text">常见权限</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E6%9D%83%E9%99%90-2"><span class="toc-number">1.13.2.</span> <span class="toc-text">运行时权限</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Git%E5%AD%A6%E4%B9%A0"><span class="toc-number">1.14.</span> <span class="toc-text">Git学习</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Git%E9%AB%98%E7%BA%A7%E7%94%A8%E6%B3%95"><span class="toc-number">1.14.1.</span> <span class="toc-text">Git高级用法</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%86%E6%94%AF%E7%9A%84%E7%94%A8%E6%B3%95"><span class="toc-number">1.14.1.1.</span> <span class="toc-text">分支的用法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%8E%E8%BF%9C%E7%A8%8B%E5%8D%8F%E4%BD%9C"><span class="toc-number">1.14.1.2.</span> <span class="toc-text">与远程协作</span></a></li></ol></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E9%9B%B6%E6%95%A3%E7%9F%A5%E8%AF%86%E5%9D%97"><span class="toc-number">2.</span> <span class="toc-text">零散知识块</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#Fragment"><span class="toc-number">2.1.</span> <span class="toc-text">Fragment</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Fragment%E4%BD%BF%E7%94%A8"><span class="toc-number">2.1.1.</span> <span class="toc-text">Fragment使用</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Acitivity%E9%9D%99%E6%80%81%E6%B7%BB%E5%8A%A0Fragment%EF%BC%9A"><span class="toc-number">2.1.1.1.</span> <span class="toc-text">Acitivity静态添加Fragment：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Activity%E5%8A%A8%E6%80%81%E6%B7%BB%E5%8A%A0%E5%92%8C%E7%AE%A1%E7%90%86Fragment%EF%BC%9A"><span class="toc-number">2.1.1.2.</span> <span class="toc-text">Activity动态添加和管理Fragment：</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Fragment%E5%92%8CActivity%E8%BF%9B%E8%A1%8C%E9%80%9A%E4%BF%A1"><span class="toc-number">2.1.2.</span> <span class="toc-text">Fragment和Activity进行通信</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8bundle%E9%80%9A%E4%BF%A1"><span class="toc-number">2.1.2.1.</span> <span class="toc-text">使用bundle通信</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Java%E6%8E%A5%E5%8F%A3%E8%BF%9B%E8%A1%8C%E9%80%9A%E4%BF%A1"><span class="toc-number">2.1.2.2.</span> <span class="toc-text">使用Java接口进行通信</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%85%B6%E4%BB%96%E6%96%B9%E6%A1%88"><span class="toc-number">2.1.2.3.</span> <span class="toc-text">其他方案</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Fragment%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">2.1.3.</span> <span class="toc-text">Fragment生命周期</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ViewPager2%E4%B8%8EFragment"><span class="toc-number">2.1.4.</span> <span class="toc-text">ViewPager2与Fragment</span></a></li></ol></li></ol></li></ol></div></div></div></div></main><footer id="footer" style="background-image: url('http://forgo7ten.gitee.io/store/imgs/10.jpg')"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By Forgo7ten</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div><div class="footer_custom_text">Hi, welcome to my <a href="https://Forgo7ten.github.io/">blog</a>!</div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">本地搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div></div></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js"></script><script src="/js/search/local-search.js"></script><script>var preloader = {
  endLoading: () => {
    document.body.style.overflow = 'auto';
    document.getElementById('loading-box').classList.add("loaded")
  },
  initLoading: () => {
    document.body.style.overflow = '';
    document.getElementById('loading-box').classList.remove("loaded")

  }
}
window.addEventListener('load',preloader.endLoading())</script><div class="js-pjax"><script>function addGitalkSource () {
  const ele = document.createElement('link')
  ele.rel = 'stylesheet'
  ele.href= 'https://cdn.jsdelivr.net/npm/gitalk/dist/gitalk.min.css'
  document.getElementsByTagName('head')[0].appendChild(ele)
}

function loadGitalk () {
  function initGitalk () {
    var gitalk = new Gitalk(Object.assign({
      clientID: '9e01c692fcf5a9e47867',
      clientSecret: '6d5297eda0643a171a9e5510f5ea1c29ad851389',
      repo: 'Forgo7ten.github.io',
      owner: 'Forgo7ten',
      admin: ['Forgo7ten'],
      id: '124691b69496cf3bf84ace6dd54b45a5',
      updateCountCallback: commentCount
    },{"language":"en","perPage":20,"distractionFreeMode":true,"pagerDirection":"last","createIssueManually":true}))

    gitalk.render('gitalk-container')
  }

  if (typeof Gitalk === 'function') initGitalk()
  else {
    addGitalkSource()
    getScript('https://cdn.jsdelivr.net/npm/gitalk@latest/dist/gitalk.min.js').then(initGitalk)
  }
}

function commentCount(n){
  let isCommentCount = document.querySelector('#post-meta .gitalk-comment-count')
  if (isCommentCount) {
    isCommentCount.innerHTML= n
  }
}

if ('Gitalk' === 'Gitalk' || !false) {
  if (false) btf.loadComment(document.getElementById('gitalk-container'), loadGitalk)
  else loadGitalk()
} else {
  function loadOtherComment () {
    loadGitalk()
  }
}</script></div><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful = true;
POWERMODE.shake = true;
POWERMODE.mobile = false;
document.body.addEventListener('input', POWERMODE);
</script><script id="click-show-text" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-show-text.min.js" data-mobile="false" data-text="ヾ(≧▽≦*)o 点个收藏叭,(*^▽^*),w(ﾟДﾟ)w,ㄟ(≧◇≦)ㄏ,(/≧▽≦)/点个关注叭,Σ(っ °Д °;)っ,(●ˇ∀ˇ●),( •̀ ω •́ )✧,(*/ω＼*),ヽ(*。&gt;Д&lt;)o゜真的不收藏一下嘛,(～o￣3￣)～,ヽ（≧□≦）ノ" data-fontsize="15px" data-random="false" async="async"></script><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>let pjaxSelectors = ["title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]

var pjax = new Pjax({
  elements: 'a:not([target="_blank"])',
  selectors: pjaxSelectors,
  cacheBust: false,
  analytics: false,
  scrollRestoration: false
})

document.addEventListener('pjax:send', function () {

  // removeEventListener scroll 
  window.tocScrollFn && window.removeEventListener('scroll', window.tocScrollFn)
  window.scrollCollect && window.removeEventListener('scroll', scrollCollect)

  typeof preloader === 'object' && preloader.initLoading()
  document.getElementById('rightside').style.cssText = "opacity: ''; transform: ''"
  
  if (window.aplayers) {
    for (let i = 0; i < window.aplayers.length; i++) {
      if (!window.aplayers[i].options.fixed) {
        window.aplayers[i].destroy()
      }
    }
  }

  typeof typed === 'object' && typed.destroy()

  //reset readmode
  const $bodyClassList = document.body.classList
  $bodyClassList.contains('read-mode') && $bodyClassList.remove('read-mode')

})

document.addEventListener('pjax:complete', function () {
  window.refreshFn()

  document.querySelectorAll('script[data-pjax]').forEach(item => {
    const newScript = document.createElement('script')
    const content = item.text || item.textContent || item.innerHTML || ""
    Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
    newScript.appendChild(document.createTextNode(content))
    item.parentNode.replaceChild(newScript, item)
  })

  GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()

  typeof chatBtnFn === 'function' && chatBtnFn()
  typeof panguInit === 'function' && panguInit()

  // google analytics
  typeof gtag === 'function' && gtag('config', '', {'page_path': window.location.pathname});

  // baidu analytics
  typeof _hmt === 'object' && _hmt.push(['_trackPageview',window.location.pathname]);

  typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()

  // prismjs
  typeof Prism === 'object' && Prism.highlightAll()

  typeof preloader === 'object' && preloader.endLoading()
})

document.addEventListener('pjax:error', (e) => {
  if (e.request.status === 404) {
    pjax.loadUrl('/404.html')
  }
})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"scale":1,"hHeadPos":0.5,"vHeadPos":0.618,"jsonPath":"/live2dw/assets/z16.model.json"},"display":{"superSample":2,"width":200,"height":400,"position":"right","hOffset":0,"vOffset":-20},"mobile":{"show":true,"scale":0.5},"react":{"opacityDefault":0.7,"opacityOnHover":0.2},"log":false});</script></body></html>